| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.tika.parser.microsoft.onenote; |
| |
| import java.io.IOException; |
| import java.util.Objects; |
| |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import org.apache.tika.exception.TikaMemoryLimitException; |
| |
| /** |
| * A FileNode structure is the basic unit for holding and referencing data in the file. |
| * FileNode structures are organized into file node lists |
| * <p> |
| * A FileNode structure is divided into header fields and a data field, fnd. The header fields |
| * specify what type of FileNode structure it |
| * is, |
| * and what format the fnd field is in. |
| * <p> |
| * The fnd field can be empty, or it can contain data directly, or it can contain a reference to |
| * another block of the file by |
| * byte position and byte count, or it can contain both data and a reference. |
| */ |
| class FileNode { |
| private static final Logger LOG = LoggerFactory.getLogger(FileNode.class); |
| |
| /** |
| * An unsigned integer that specifies the type of this FileNode structure. The meaning of |
| * this value is specified by the fnd field. |
| */ |
| long id; |
| long size; |
| |
| /** |
| * An unsigned integer that specifies whether the structure specified by fnd contains a |
| * FileNodeChunkReference structure. |
| * 0 - This FileNode structure does not reference other data. The data structure specified |
| * by fnd MUST NOT contain a |
| * FileNodeChunkReference structure. The StpFormat and CbFormat fields MUST be ignored. |
| * 1 - This FileNode structure contains a reference to data. The first field in the data |
| * structure specified by an fnd field MUST be a |
| * FileNodeChunkReference structure that specifies the location and size of the referenced |
| * data. |
| * The type of the FileNodeChunkReference structure is specified by the StpFormat and |
| * CbFormat fields. |
| * 2 - This FileNode structure contains a reference to a file node list. |
| * The first field in the data structure specified by the fnd field MUST be a |
| * FileNodeChunkReference structure that specifies the |
| * location and size of a file node list. The type of the FileNodeChunkReference is |
| * specified by the StpFormat and CbFormat fields. |
| */ |
| long baseType; |
| |
| /** |
| * The ExtendedGUID for this FileNode. |
| * Specified for ObjectSpaceManifestRoot |
| * ObjectSpaceManifestStart |
| * ObjectSpaceManifestList |
| * RevisionManifestListStart |
| * ObjectGroupStartFND |
| * ObjectGroupID |
| * ObjectGroupListReferenceFND |
| * <p> |
| * RID for RevisionManifestStart4FND |
| * DataSignatureGroup for RevisionManifestEndFND |
| */ |
| ExtendedGUID gosid; |
| |
| // only present for RevisionManfiest7FND and RevisionRoleAndContextDeclaration |
| ExtendedGUID gctxid; |
| GUID fileDataStoreReference; |
| FileChunkReference ref; |
| PropertySet propertySet; |
| boolean isFileData; |
| |
| /** |
| * For ObjectGroupListReference, the children. |
| */ |
| FileNodeList childFileNodeList = new FileNodeList(); |
| |
| FileNodeUnion subType = new FileNodeUnion(); |
| |
| String idDesc; |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) { |
| return false; |
| } |
| FileNode fileNode = (FileNode) o; |
| return id == fileNode.id && size == fileNode.size && baseType == fileNode.baseType && |
| isFileData == fileNode.isFileData && Objects.equals(gosid, fileNode.gosid) && |
| Objects.equals(gctxid, fileNode.gctxid) && |
| Objects.equals(fileDataStoreReference, fileNode.fileDataStoreReference) && |
| Objects.equals(ref, fileNode.ref) && |
| Objects.equals(propertySet, fileNode.propertySet) && |
| Objects.equals(childFileNodeList, fileNode.childFileNodeList) && |
| Objects.equals(subType, fileNode.subType); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects |
| .hash(id, size, baseType, gosid, gctxid, fileDataStoreReference, ref, propertySet, |
| isFileData, childFileNodeList, subType); |
| } |
| |
| public boolean hasGctxid() { |
| return id == FndStructureConstants.RevisionRoleAndContextDeclarationFND || |
| id == FndStructureConstants.RevisionManifestStart7FND; |
| } |
| |
| public long getId() { |
| return id; |
| } |
| |
| public FileNode setId(long id) { |
| this.id = id; |
| return this; |
| } |
| |
| public long getSize() { |
| return size; |
| } |
| |
| public FileNode setSize(long size) { |
| this.size = size; |
| return this; |
| } |
| |
| public long getBaseType() { |
| return baseType; |
| } |
| |
| public FileNode setBaseType(long baseType) { |
| this.baseType = baseType; |
| return this; |
| } |
| |
| public ExtendedGUID getGosid() { |
| return gosid; |
| } |
| |
| public FileNode setGosid(ExtendedGUID gosid) { |
| this.gosid = gosid; |
| return this; |
| } |
| |
| public ExtendedGUID getGctxid() { |
| return gctxid; |
| } |
| |
| public FileNode setGctxid(ExtendedGUID gctxid) { |
| this.gctxid = gctxid; |
| return this; |
| } |
| |
| public GUID getFileDataStoreReference() { |
| return fileDataStoreReference; |
| } |
| |
| public FileNode setFileDataStoreReference(GUID fileDataStoreReference) { |
| this.fileDataStoreReference = fileDataStoreReference; |
| return this; |
| } |
| |
| public FileChunkReference getRef() { |
| return ref; |
| } |
| |
| public FileNode setRef(FileChunkReference ref) { |
| this.ref = ref; |
| return this; |
| } |
| |
| public PropertySet getPropertySet() { |
| return propertySet; |
| } |
| |
| public FileNode setPropertySet(PropertySet propertySet) { |
| this.propertySet = propertySet; |
| return this; |
| } |
| |
| public boolean isFileData() { |
| return isFileData; |
| } |
| |
| public FileNode setFileData(boolean fileData) { |
| isFileData = fileData; |
| return this; |
| } |
| |
| public FileNodeList getChildFileNodeList() { |
| return childFileNodeList; |
| } |
| |
| public FileNode setChildFileNodeList(FileNodeList childFileNodeList) { |
| this.childFileNodeList = childFileNodeList; |
| return this; |
| } |
| |
| public FileNodeUnion getSubType() { |
| return subType; |
| } |
| |
| public FileNode setSubType(FileNodeUnion subType) { |
| this.subType = subType; |
| return this; |
| } |
| |
| public void print(OneNoteDocument document, OneNotePtr pointer, int indentLevel) |
| throws IOException, TikaMemoryLimitException { |
| boolean shouldPrintHeader = FndStructureConstants.nameOf(id).contains("ObjectDec"); |
| if (gosid.equals(ExtendedGUID.nil()) && shouldPrintHeader) { |
| LOG.debug("{}[beg {}]:{}", IndentUtil.getIndent(indentLevel + 1), |
| FndStructureConstants.nameOf(id), gosid); |
| } |
| propertySet.print(document, pointer, indentLevel + 1); |
| if (!childFileNodeList.children.isEmpty()) { |
| if (shouldPrintHeader) { |
| LOG.debug("{}children", IndentUtil.getIndent(indentLevel + 1)); |
| } |
| for (FileNode child : childFileNodeList.children) { |
| child.print(document, pointer, indentLevel + 1); |
| } |
| } |
| if (id == FndStructureConstants.RevisionRoleDeclarationFND || |
| id == FndStructureConstants.RevisionRoleAndContextDeclarationFND) { |
| LOG.debug("{}[Revision Role {}]", IndentUtil.getIndent(indentLevel + 1), |
| subType.revisionRoleDeclaration.revisionRole); |
| |
| } |
| if (id == FndStructureConstants.RevisionManifestStart4FND || |
| id == FndStructureConstants.RevisionManifestStart6FND || |
| id == FndStructureConstants.RevisionManifestStart7FND) { |
| LOG.debug("{}[revisionRole {}]", IndentUtil.getIndent(indentLevel + 1), |
| subType.revisionManifest.revisionRole); |
| |
| } |
| if ((gctxid != ExtendedGUID.nil() || |
| id == FndStructureConstants.RevisionManifestStart7FND) && shouldPrintHeader) { |
| LOG.debug("{}[gctxid {}]", IndentUtil.getIndent(indentLevel + 1), gctxid); |
| } |
| if (gosid != ExtendedGUID.nil() && shouldPrintHeader) { |
| LOG.debug("{}[end {}]:{}", IndentUtil.getIndent(indentLevel + 1), |
| FndStructureConstants.nameOf(id), gosid); |
| |
| } |
| } |
| |
| /** |
| * A description of what this GUID id means in this context. |
| * |
| * @return A description of what this GUID id means in this context. |
| */ |
| public String getIdDesc() { |
| return idDesc; |
| } |
| |
| @Override |
| public String toString() { |
| return new StringBuilder().append("FileNodeID=0x").append(Long.toHexString(id)) |
| .append(", gosid=").append(gosid).append(", baseType=0x") |
| .append(Long.toHexString(baseType)).toString(); |
| } |
| } |