org.sejda.sambox.pdmodel.documentinterchange.logicalstructure.PDStructureElement Maven / Gradle / Ivy
/*
* 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.sejda.sambox.pdmodel.documentinterchange.logicalstructure;
import java.util.Iterator;
import java.util.Map;
import org.sejda.sambox.cos.COSArray;
import org.sejda.sambox.cos.COSBase;
import org.sejda.sambox.cos.COSDictionary;
import org.sejda.sambox.cos.COSInteger;
import org.sejda.sambox.cos.COSName;
import org.sejda.sambox.pdmodel.PDPage;
import org.sejda.sambox.pdmodel.documentinterchange.markedcontent.PDMarkedContent;
/**
* A structure element.
*
* @author Ben Litchfield
* @author Johannes Koch
*/
public class PDStructureElement extends PDStructureNode
{
public static final String TYPE = "StructElem";
/**
* Constructor with required values.
*
* @param structureType the structure type
* @param parent the parent structure node
*/
public PDStructureElement(String structureType, PDStructureNode parent)
{
super(TYPE);
this.setStructureType(structureType);
this.setParent(parent);
}
/**
* Constructor for an existing structure element.
*
* @param dic The existing dictionary.
*/
public PDStructureElement( COSDictionary dic )
{
super(dic);
}
/**
* Returns the structure type (S).
*
* @return the structure type
*/
public String getStructureType()
{
return this.getCOSObject().getNameAsString(COSName.S);
}
/**
* Sets the structure type (S).
*
* @param structureType the structure type
*/
public final void setStructureType(String structureType)
{
this.getCOSObject().setName(COSName.S, structureType);
}
/**
* Returns the parent in the structure hierarchy (P).
*
* @return the parent in the structure hierarchy
*/
public PDStructureNode getParent()
{
COSBase base = this.getCOSObject().getDictionaryObject(COSName.P);
if (base instanceof COSDictionary)
{
return PDStructureNode.create((COSDictionary) base);
}
return null;
}
/**
* Sets the parent in the structure hierarchy (P).
*
* @param structureNode the parent in the structure hierarchy
*/
public final void setParent(PDStructureNode structureNode)
{
this.getCOSObject().setItem(COSName.P, structureNode);
}
/**
* Returns the element identifier (ID).
*
* @return the element identifier
*/
public String getElementIdentifier()
{
return this.getCOSObject().getString(COSName.ID);
}
/**
* Sets the element identifier (ID).
*
* @param id the element identifier
*/
public void setElementIdentifier(String id)
{
this.getCOSObject().setString(COSName.ID, id);
}
/**
* Returns the page on which some or all of the content items designated by
* the K entry shall be rendered (Pg).
*
* @return the page on which some or all of the content items designated by
* the K entry shall be rendered
*/
public PDPage getPage()
{
COSBase base = this.getCOSObject().getDictionaryObject(COSName.PG);
if (base instanceof COSDictionary)
{
return new PDPage((COSDictionary) base);
}
return null;
}
/**
* Sets the page on which some or all of the content items designated by
* the K entry shall be rendered (Pg).
* @param page the page on which some or all of the content items designated
* by the K entry shall be rendered.
*/
public void setPage(PDPage page)
{
this.getCOSObject().setItem(COSName.PG, page);
}
/**
* Returns the attributes together with their revision numbers (A).
*
* @return the attributes
*/
public Revisions getAttributes()
{
Revisions attributes =
new Revisions<>();
COSBase a = this.getCOSObject().getDictionaryObject(COSName.A);
if (a instanceof COSArray aa)
{
Iterator it = aa.iterator();
PDAttributeObject ao = null;
while (it.hasNext())
{
COSBase item = it.next().getCOSObject();
if (item instanceof COSDictionary)
{
ao = PDAttributeObject.create((COSDictionary) item);
ao.setStructureElement(this);
attributes.addObject(ao, 0);
}
else if (item instanceof COSInteger)
{
attributes.setRevisionNumber(ao,
((COSInteger) item).intValue());
}
}
}
if (a instanceof COSDictionary)
{
PDAttributeObject ao = PDAttributeObject.create((COSDictionary) a);
ao.setStructureElement(this);
attributes.addObject(ao, 0);
}
return attributes;
}
/**
* Sets the attributes together with their revision numbers (A).
*
* @param attributes the attributes
*/
public void setAttributes(Revisions attributes)
{
COSName key = COSName.A;
if ((attributes.size() == 1) && (attributes.getRevisionNumber(0) == 0))
{
PDAttributeObject attributeObject = attributes.getObject(0);
attributeObject.setStructureElement(this);
this.getCOSObject().setItem(key, attributeObject);
return;
}
COSArray array = new COSArray();
for (int i = 0; i < attributes.size(); i++)
{
PDAttributeObject attributeObject = attributes.getObject(i);
attributeObject.setStructureElement(this);
int revisionNumber = attributes.getRevisionNumber(i);
if (revisionNumber < 0)
{
throw new IllegalArgumentException("The revision number shall be > -1");
}
array.add(attributeObject);
array.add(COSInteger.get(revisionNumber));
}
this.getCOSObject().setItem(key, array);
}
/**
* Adds an attribute object.
*
* @param attributeObject the attribute object
*/
public void addAttribute(PDAttributeObject attributeObject)
{
COSName key = COSName.A;
attributeObject.setStructureElement(this);
COSBase a = this.getCOSObject().getDictionaryObject(key);
COSArray array;
if (a instanceof COSArray)
{
array = (COSArray) a;
}
else
{
array = new COSArray();
if (a != null)
{
array.add(a);
array.add(COSInteger.get(0));
}
}
this.getCOSObject().setItem(key, array);
array.add(attributeObject);
array.add(COSInteger.get(this.getRevisionNumber()));
}
/**
* Removes an attribute object.
*
* @param attributeObject the attribute object
*/
public void removeAttribute(PDAttributeObject attributeObject)
{
COSName key = COSName.A;
COSBase a = this.getCOSObject().getDictionaryObject(key);
if (a instanceof COSArray array)
{
array.remove(attributeObject.getCOSObject());
if ((array.size() == 2) && (array.getInt(1) == 0))
{
this.getCOSObject().setItem(key, array.getObject(0));
}
}
else
{
if (attributeObject.getCOSObject().equals(a.getCOSObject()))
{
this.getCOSObject().removeItem(key);
}
}
attributeObject.setStructureElement(null);
}
/**
* Updates the revision number for the given attribute object.
*
* @param attributeObject the attribute object
*/
public void attributeChanged(PDAttributeObject attributeObject)
{
COSName key = COSName.A;
COSBase a = this.getCOSObject().getDictionaryObject(key);
if (a instanceof COSArray array)
{
for (int i = 0; i < array.size(); i++)
{
COSBase entry = array.getObject(i);
if (entry.equals(attributeObject.getCOSObject()))
{
COSBase next = array.get(i + 1);
if (next instanceof COSInteger)
{
array.set(i + 1, COSInteger.get(this.getRevisionNumber()));
}
}
}
}
else
{
COSArray array = new COSArray();
array.add(a);
array.add(COSInteger.get(this.getRevisionNumber()));
this.getCOSObject().setItem(key, array);
}
}
/**
* Returns the class names together with their revision numbers (C).
*
* @return the class names
*/
public Revisions getClassNames()
{
COSName key = COSName.C;
Revisions classNames = new Revisions<>();
COSBase c = this.getCOSObject().getDictionaryObject(key);
if (c instanceof COSName)
{
classNames.addObject(((COSName) c).getName(), 0);
}
if (c instanceof COSArray array)
{
Iterator it = array.iterator();
String className = null;
while (it.hasNext())
{
COSBase item = it.next().getCOSObject();
if (item instanceof COSName)
{
className = ((COSName) item).getName();
classNames.addObject(className, 0);
}
else if (item instanceof COSInteger)
{
classNames.setRevisionNumber(className,
((COSInteger) item).intValue());
}
}
}
return classNames;
}
/**
* Sets the class names together with their revision numbers (C).
*
* @param classNames the class names
*/
public void setClassNames(Revisions classNames)
{
if (classNames == null)
{
return;
}
COSName key = COSName.C;
if ((classNames.size() == 1) && (classNames.getRevisionNumber(0) == 0))
{
String className = classNames.getObject(0);
this.getCOSObject().setName(key, className);
return;
}
COSArray array = new COSArray();
for (int i = 0; i < classNames.size(); i++)
{
String className = classNames.getObject(i);
int revisionNumber = classNames.getRevisionNumber(i);
if (revisionNumber < 0)
{
throw new IllegalArgumentException("The revision number shall be > -1");
}
array.add(COSName.getPDFName(className));
array.add(COSInteger.get(revisionNumber));
}
this.getCOSObject().setItem(key, array);
}
/**
* Adds a class name.
*
* @param className the class name
*/
public void addClassName(String className)
{
if (className == null)
{
return;
}
COSName key = COSName.C;
COSBase c = this.getCOSObject().getDictionaryObject(key);
COSArray array;
if (c instanceof COSArray)
{
array = (COSArray) c;
}
else
{
array = new COSArray();
if (c != null)
{
array.add(c);
array.add(COSInteger.get(0));
}
}
this.getCOSObject().setItem(key, array);
array.add(COSName.getPDFName(className));
array.add(COSInteger.get(this.getRevisionNumber()));
}
/**
* Removes a class name.
*
* @param className the class name
*/
public void removeClassName(String className)
{
if (className == null)
{
return;
}
COSName key = COSName.C;
COSBase c = this.getCOSObject().getDictionaryObject(key);
COSName name = COSName.getPDFName(className);
if (c instanceof COSArray array)
{
array.remove(name);
if ((array.size() == 2) && (array.getInt(1) == 0))
{
this.getCOSObject().setItem(key, array.getObject(0));
}
}
else
{
if (name.equals(c.getCOSObject()))
{
this.getCOSObject().removeItem(key);
}
}
}
/**
* Returns the revision number (R).
*
* @return the revision number
*/
public int getRevisionNumber()
{
return this.getCOSObject().getInt(COSName.R, 0);
}
/**
* Sets the revision number (R).
*
* @param revisionNumber the revision number
*/
public void setRevisionNumber(int revisionNumber)
{
if (revisionNumber < 0)
{
throw new IllegalArgumentException("The revision number shall be > -1");
}
this.getCOSObject().setInt(COSName.R, revisionNumber);
}
/**
* Increments th revision number.
*/
public void incrementRevisionNumber()
{
this.setRevisionNumber(this.getRevisionNumber() + 1);
}
/**
* Returns the title (T).
*
* @return the title
*/
public String getTitle()
{
return this.getCOSObject().getString(COSName.T);
}
/**
* Sets the title (T).
*
* @param title the title
*/
public void setTitle(String title)
{
this.getCOSObject().setString(COSName.T, title);
}
/**
* Returns the language (Lang).
*
* @return the language
*/
public String getLanguage()
{
return this.getCOSObject().getString(COSName.LANG);
}
/**
* Sets the language (Lang).
*
* @param language the language
*/
public void setLanguage(String language)
{
this.getCOSObject().setString(COSName.LANG, language);
}
/**
* Returns the alternate description (Alt).
*
* @return the alternate description
*/
public String getAlternateDescription()
{
return this.getCOSObject().getString(COSName.ALT);
}
/**
* Sets the alternate description (Alt).
*
* @param alternateDescription the alternate description
*/
public void setAlternateDescription(String alternateDescription)
{
this.getCOSObject().setString(COSName.ALT, alternateDescription);
}
/**
* Returns the expanded form (E).
*
* @return the expanded form
*/
public String getExpandedForm()
{
return this.getCOSObject().getString(COSName.E);
}
/**
* Sets the expanded form (E).
*
* @param expandedForm the expanded form
*/
public void setExpandedForm(String expandedForm)
{
this.getCOSObject().setString(COSName.E, expandedForm);
}
/**
* Returns the actual text (ActualText).
*
* @return the actual text
*/
public String getActualText()
{
return this.getCOSObject().getString(COSName.ACTUAL_TEXT);
}
/**
* Sets the actual text (ActualText).
*
* @param actualText the actual text
*/
public void setActualText(String actualText)
{
this.getCOSObject().setString(COSName.ACTUAL_TEXT, actualText);
}
/**
* Returns the standard structure type, the actual structure type is mapped
* to in the role map.
*
* @return the standard structure type
*/
public String getStandardStructureType()
{
String type = this.getStructureType();
Map roleMap = getRoleMap();
if (roleMap.containsKey(type))
{
Object mappedValue = getRoleMap().get(type);
if (mappedValue instanceof String)
{
type = (String)mappedValue;
}
}
return type;
}
/**
* Appends a marked-content sequence kid.
*
* @param markedContent the marked-content sequence
*/
public void appendKid(PDMarkedContent markedContent)
{
if (markedContent == null)
{
return;
}
this.appendKid(COSInteger.get(markedContent.getMCID()));
}
/**
* Appends a marked-content reference kid.
*
* @param markedContentReference the marked-content reference
*/
public void appendKid(PDMarkedContentReference markedContentReference)
{
this.appendObjectableKid(markedContentReference);
}
/**
* Appends an object reference kid.
*
* @param objectReference the object reference
*/
public void appendKid(PDObjectReference objectReference)
{
this.appendObjectableKid(objectReference);
}
/**
* Inserts a marked-content identifier kid before a reference kid.
*
* @param markedContentIdentifier the marked-content identifier
* @param refKid the reference kid
*/
public void insertBefore(COSInteger markedContentIdentifier, Object refKid)
{
this.insertBefore((COSBase) markedContentIdentifier, refKid);
}
/**
* Inserts a marked-content reference kid before a reference kid.
*
* @param markedContentReference the marked-content reference
* @param refKid the reference kid
*/
public void insertBefore(PDMarkedContentReference markedContentReference,
Object refKid)
{
this.insertObjectableBefore(markedContentReference, refKid);
}
/**
* Inserts an object reference kid before a reference kid.
*
* @param objectReference the object reference
* @param refKid the reference kid
*/
public void insertBefore(PDObjectReference objectReference, Object refKid)
{
this.insertObjectableBefore(objectReference, refKid);
}
/**
* Removes a marked-content identifier kid.
*
* @param markedContentIdentifier the marked-content identifier
*/
public void removeKid(COSInteger markedContentIdentifier)
{
this.removeKid((COSBase) markedContentIdentifier);
}
/**
* Removes a marked-content reference kid.
*
* @param markedContentReference the marked-content reference
*/
public void removeKid(PDMarkedContentReference markedContentReference)
{
this.removeObjectableKid(markedContentReference);
}
/**
* Removes an object reference kid.
*
* @param objectReference the object reference
*/
public void removeKid(PDObjectReference objectReference)
{
this.removeObjectableKid(objectReference);
}
/**
* Returns the structure tree root.
*
* @return the structure tree root
*/
private PDStructureTreeRoot getStructureTreeRoot()
{
PDStructureNode parent = this.getParent();
while (parent instanceof PDStructureElement)
{
parent = ((PDStructureElement) parent).getParent();
}
if (parent instanceof PDStructureTreeRoot)
{
return (PDStructureTreeRoot) parent;
}
return null;
}
/**
* Returns the role map.
*
* @return the role map
*/
private Map getRoleMap()
{
PDStructureTreeRoot root = this.getStructureTreeRoot();
if (root != null)
{
return root.getRoleMap();
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy