]> _ Git - cubeextranet.git/blob
2b7fd644bc4df7f7315ff7c60eb279630f8aba2d
[cubeextranet.git] /
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure;
18
19 import java.util.Iterator;
20 import java.util.Map;
21
22 import org.apache.pdfbox.cos.COSArray;
23 import org.apache.pdfbox.cos.COSBase;
24 import org.apache.pdfbox.cos.COSDictionary;
25 import org.apache.pdfbox.cos.COSInteger;
26 import org.apache.pdfbox.cos.COSName;
27 import org.apache.pdfbox.cos.COSObject;
28 import org.apache.pdfbox.pdmodel.PDPage;
29 import org.apache.pdfbox.pdmodel.documentinterchange.markedcontent.PDMarkedContent;
30
31 /**
32  * A structure element.
33  *
34  * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>,
35  *  <a href="mailto:Johannes%20Koch%20%3Ckoch@apache.org%3E">Johannes Koch</a>
36  * @version $Revision: 1.3 $
37  */
38 public class PDStructureElement extends PDStructureNode
39 {
40     public static final String TYPE = "StructElem";
41
42
43     /**
44      * Constructor with required values.
45      *
46      * @param structureType the structure type
47      * @param parent the parent structure node
48      */
49     public PDStructureElement(String structureType, PDStructureNode parent)
50     {
51         super(TYPE);
52         this.setStructureType(structureType);
53         this.setParent(parent);
54     }
55
56     /**
57      * Constructor for an existing structure element.
58      *
59      * @param dic The existing dictionary.
60      */
61     public PDStructureElement( COSDictionary dic )
62     {
63         super(dic);
64     }
65
66
67     /**
68      * Returns the structure type (S).
69      * 
70      * @return the structure type
71      */
72     public String getStructureType()
73     {
74         return this.getCOSDictionary().getNameAsString(COSName.S);
75     }
76
77     /**
78      * Sets the structure type (S).
79      * 
80      * @param structureType the structure type
81      */
82     public void setStructureType(String structureType)
83     {
84         this.getCOSDictionary().setName(COSName.S, structureType);
85     }
86
87     /**
88      * Returns the parent in the structure hierarchy (P).
89      * 
90      * @return the parent in the structure hierarchy
91      */
92     public PDStructureNode getParent()
93     {
94         COSDictionary p = (COSDictionary) this.getCOSDictionary()
95             .getDictionaryObject(COSName.P);
96         if (p == null)
97         {
98             return null;
99         }
100         return PDStructureNode.create((COSDictionary) p);
101     }
102
103     /**
104      * Sets the parent in the structure hierarchy (P).
105      * 
106      * @param structureNode the parent in the structure hierarchy
107      */
108     public void setParent(PDStructureNode structureNode)
109     {
110         this.getCOSDictionary().setItem(COSName.P, structureNode);
111     }
112
113     /**
114      * Returns the element identifier (ID).
115      * 
116      * @return the element identifier
117      */
118     public String getElementIdentifier()
119     {
120         return this.getCOSDictionary().getString(COSName.ID);
121     }
122
123     /**
124      * Sets the element identifier (ID).
125      * 
126      * @param id the element identifier
127      */
128     public void setElementIdentifier(String id)
129     {
130         this.getCOSDictionary().setString(COSName.ID, id);
131     }
132
133     /**
134      * Returns the page on which some or all of the content items designated by
135      *  the K entry shall be rendered (Pg).
136      * 
137      * @return the page on which some or all of the content items designated by
138      *  the K entry shall be rendered
139      */
140     public PDPage getPage()
141     {
142         COSDictionary pageDic = (COSDictionary) this.getCOSDictionary()
143             .getDictionaryObject(COSName.PG);
144         if (pageDic == null)
145         {
146             return null;
147         }
148         return new PDPage(pageDic);
149     }
150
151     /**
152      * Sets the page on which some or all of the content items designated by
153      *  the K entry shall be rendered (Pg).
154      * @param page the page on which some or all of the content items designated
155      *  by the K entry shall be rendered.
156      */
157     public void setPage(PDPage page)
158     {
159         this.getCOSDictionary().setItem(COSName.PG, page);
160     }
161
162     /**
163      * Returns the attributes together with their revision numbers (A).
164      * 
165      * @return the attributes
166      */
167     public Revisions<PDAttributeObject> getAttributes()
168     {
169         Revisions<PDAttributeObject> attributes =
170             new Revisions<PDAttributeObject>();
171         COSBase a = this.getCOSDictionary().getDictionaryObject(COSName.A);
172         if (a instanceof COSArray)
173         {
174             COSArray aa = (COSArray) a;
175             Iterator<COSBase> it = aa.iterator();
176             PDAttributeObject ao = null;
177             while (it.hasNext())
178             {
179                 COSBase item = it.next();
180                 if (item instanceof COSDictionary)
181                 {
182                     ao = PDAttributeObject.create((COSDictionary) item);
183                     ao.setStructureElement(this);
184                     attributes.addObject(ao, 0);
185                 }
186                 else if (item instanceof COSInteger)
187                 {
188                     attributes.setRevisionNumber(ao,
189                         ((COSInteger) item).intValue());
190                 }
191             }
192         }
193         if (a instanceof COSDictionary)
194         {
195             PDAttributeObject ao = PDAttributeObject.create((COSDictionary) a);
196             ao.setStructureElement(this);
197             attributes.addObject(ao, 0);
198         }
199         return attributes;
200     }
201
202     /**
203      * Sets the attributes together with their revision numbers (A).
204      * 
205      * @param attributes the attributes
206      */
207     public void setAttributes(Revisions<PDAttributeObject> attributes)
208     {
209         COSName key = COSName.A;
210         if ((attributes.size() == 1) && (attributes.getRevisionNumber(0) == 0))
211         {
212             PDAttributeObject attributeObject = attributes.getObject(0);
213             attributeObject.setStructureElement(this);
214             this.getCOSDictionary().setItem(key, attributeObject);
215             return;
216         }
217         COSArray array = new COSArray();
218         for (int i = 0; i < attributes.size(); i++)
219         {
220             PDAttributeObject attributeObject = attributes.getObject(i);
221             attributeObject.setStructureElement(this);
222             int revisionNumber = attributes.getRevisionNumber(i);
223             if (revisionNumber < 0)
224             {
225                 // TODO throw Exception because revision number must be > -1?
226             }
227             array.add(attributeObject);
228             array.add(COSInteger.get(revisionNumber));
229         }
230         this.getCOSDictionary().setItem(key, array);
231     }
232
233     /**
234      * Adds an attribute object.
235      * 
236      * @param attributeObject the attribute object
237      */
238     public void addAttribute(PDAttributeObject attributeObject)
239     {
240         COSName key = COSName.A;
241         attributeObject.setStructureElement(this);
242         COSBase a = this.getCOSDictionary().getDictionaryObject(key);
243         COSArray array = null;
244         if (a instanceof COSArray)
245         {
246             array = (COSArray) a;
247         }
248         else
249         {
250             array = new COSArray();
251             if (a != null)
252             {
253                 array.add(a);
254                 array.add(COSInteger.get(0));
255             }
256         }
257         this.getCOSDictionary().setItem(key, array);
258         array.add(attributeObject);
259         array.add(COSInteger.get(this.getRevisionNumber()));
260     }
261
262     /**
263      * Removes an attribute object.
264      * 
265      * @param attributeObject the attribute object
266      */
267     public void removeAttribute(PDAttributeObject attributeObject)
268     {
269         COSName key = COSName.A;
270         COSBase a = this.getCOSDictionary().getDictionaryObject(key);
271         if (a instanceof COSArray)
272         {
273             COSArray array = (COSArray) a;
274             array.remove(attributeObject.getCOSObject());
275             if ((array.size() == 2) && (array.getInt(1) == 0))
276             {
277                 this.getCOSDictionary().setItem(key, array.getObject(0));
278             }
279         }
280         else
281         {
282             COSBase directA = a;
283             if (a instanceof COSObject)
284             {
285                 directA = ((COSObject) a).getObject();
286             }
287             if (attributeObject.getCOSObject().equals(directA))
288             {
289                 this.getCOSDictionary().setItem(key, null);
290             }
291         }
292         attributeObject.setStructureElement(null);
293     }
294
295     /**
296      * Updates the revision number for the given attribute object.
297      * 
298      * @param attributeObject the attribute object
299      */
300     public void attributeChanged(PDAttributeObject attributeObject)
301     {
302         COSName key = COSName.A;
303         COSBase a = this.getCOSDictionary().getDictionaryObject(key);
304         if (a instanceof COSArray)
305         {
306             COSArray array = (COSArray) a;
307             for (int i = 0; i < array.size(); i++)
308             {
309                 COSBase entry = array.getObject(i);
310                 if (entry.equals(attributeObject.getCOSObject()))
311                 {
312                     COSBase next = array.get(i + 1);
313                     if (next instanceof COSInteger)
314                     {
315                         array.set(i + 1, COSInteger.get(this.getRevisionNumber()));
316                     }
317                 }
318             }
319         }
320         else
321         {
322             COSArray array = new COSArray();
323             array.add(a);
324             array.add(COSInteger.get(this.getRevisionNumber()));
325             this.getCOSDictionary().setItem(key, array);
326         }
327     }
328
329     /**
330      * Returns the class names together with their revision numbers (C).
331      * 
332      * @return the class names
333      */
334     public Revisions<String> getClassNames()
335     {
336         COSName key = COSName.C;
337         Revisions<String> classNames = new Revisions<String>();
338         COSBase c = this.getCOSDictionary().getDictionaryObject(key);
339         if (c instanceof COSName)
340         {
341             classNames.addObject(((COSName) c).getName(), 0);
342         }
343         if (c instanceof COSArray)
344         {
345             COSArray array = (COSArray) c;
346             Iterator<COSBase> it = array.iterator();
347             String className = null;
348             while (it.hasNext())
349             {
350                 COSBase item = it.next();
351                 if (item instanceof COSName)
352                 {
353                     className = ((COSName) item).getName();
354                     classNames.addObject(className, 0);
355                 }
356                 else if (item instanceof COSInteger)
357                 {
358                     classNames.setRevisionNumber(className,
359                         ((COSInteger) item).intValue());
360                 }
361             }
362         }
363         return classNames;
364     }
365
366     /**
367      * Sets the class names together with their revision numbers (C).
368      * 
369      * @param classNames the class names
370      */
371     public void setClassNames(Revisions<String> classNames)
372     {
373         if (classNames == null)
374         {
375             return;
376         }
377         COSName key = COSName.C;
378         if ((classNames.size() == 1) && (classNames.getRevisionNumber(0) == 0))
379         {
380             String className = classNames.getObject(0);
381             this.getCOSDictionary().setName(key, className);
382             return;
383         }
384         COSArray array = new COSArray();
385         for (int i = 0; i < classNames.size(); i++)
386         {
387             String className = classNames.getObject(i);
388             int revisionNumber = classNames.getRevisionNumber(i);
389             if (revisionNumber < 0)
390             {
391                 // TODO throw Exception because revision number must be > -1?
392             }
393             array.add(COSName.getPDFName(className));
394             array.add(COSInteger.get(revisionNumber));
395         }
396         this.getCOSDictionary().setItem(key, array);
397     }
398
399     /**
400      * Adds a class name.
401      * 
402      * @param className the class name
403      */
404     public void addClassName(String className)
405     {
406         if (className == null)
407         {
408             return;
409         }
410         COSName key = COSName.C;
411         COSBase c = this.getCOSDictionary().getDictionaryObject(key);
412         COSArray array = null;
413         if (c instanceof COSArray)
414         {
415             array = (COSArray) c;
416         }
417         else
418         {
419             array = new COSArray();
420             if (c != null)
421             {
422                 array.add(c);
423                 array.add(COSInteger.get(0));
424             }
425         }
426         this.getCOSDictionary().setItem(key, array);
427         array.add(COSName.getPDFName(className));
428         array.add(COSInteger.get(this.getRevisionNumber()));
429     }
430
431     /**
432      * Removes a class name.
433      * 
434      * @param className the class name
435      */
436     public void removeClassName(String className)
437     {
438         if (className == null)
439         {
440             return;
441         }
442         COSName key = COSName.C;
443         COSBase c = this.getCOSDictionary().getDictionaryObject(key);
444         COSName name = COSName.getPDFName(className);
445         if (c instanceof COSArray)
446         {
447             COSArray array = (COSArray) c;
448             array.remove(name);
449             if ((array.size() == 2) && (array.getInt(1) == 0))
450             {
451                 this.getCOSDictionary().setItem(key, array.getObject(0));
452             }
453         }
454         else
455         {
456             COSBase directC = c;
457             if (c instanceof COSObject)
458             {
459                 directC = ((COSObject) c).getObject();
460             }
461             if (name.equals(directC))
462             {
463                 this.getCOSDictionary().setItem(key, null);
464             }
465         }
466     }
467
468     /**
469      * Returns the revision number (R).
470      * 
471      * @return the revision number
472      */
473     public int getRevisionNumber()
474     {
475         return this.getCOSDictionary().getInt(COSName.R, 0);
476     }
477
478     /**
479      * Sets the revision number (R).
480      * 
481      * @param revisionNumber the revision number
482      */
483     public void setRevisionNumber(int revisionNumber)
484     {
485         if (revisionNumber < 0)
486         {
487             // TODO throw Exception because revision number must be > -1?
488         }
489         this.getCOSDictionary().setInt(COSName.R, revisionNumber);
490     }
491
492     /**
493      * Increments th revision number
494      */
495     public void incrementRevisionNumber()
496     {
497         this.setRevisionNumber(this.getRevisionNumber() + 1);
498     }
499
500     /**
501      * Returns the title (T).
502      * 
503      * @return the title
504      */
505     public String getTitle()
506     {
507         return this.getCOSDictionary().getString(COSName.T);
508     }
509
510     /**
511      * Sets the title (T).
512      * 
513      * @param title the title
514      */
515     public void setTitle(String title)
516     {
517         this.getCOSDictionary().setString(COSName.T, title);
518     }
519
520     /**
521      * Returns the language (Lang).
522      * 
523      * @return the language
524      */
525     public String getLanguage()
526     {
527         return this.getCOSDictionary().getString(COSName.LANG);
528     }
529
530     /**
531      * Sets the language (Lang).
532      * 
533      * @param language the language
534      */
535     public void setLanguage(String language)
536     {
537         this.getCOSDictionary().setString(COSName.LANG, language);
538     }
539
540     /**
541      * Returns the alternate description (Alt).
542      * 
543      * @return the alternate description
544      */
545     public String getAlternateDescription()
546     {
547         return this.getCOSDictionary().getString(COSName.ALT);
548     }
549
550     /**
551      * Sets the alternate description (Alt).
552      * 
553      * @param alternateDescription the alternate description
554      */
555     public void setAlternateDescription(String alternateDescription)
556     {
557         this.getCOSDictionary().setString(COSName.ALT, alternateDescription);
558     }
559
560     /**
561      * Returns the expanded form (E).
562      * 
563      * @return the expanded form
564      */
565     public String getExpandedForm()
566     {
567         return this.getCOSDictionary().getString(COSName.E);
568     }
569
570     /**
571      * Sets the expanded form (E).
572      * 
573      * @param expandedForm the expanded form
574      */
575     public void setExpandedForm(String expandedForm)
576     {
577         this.getCOSDictionary().setString(COSName.E, expandedForm);
578     }
579
580     /**
581      * Returns the actual text (ActualText).
582      * 
583      * @return the actual text
584      */
585     public String getActualText()
586     {
587         return this.getCOSDictionary().getString(COSName.ACTUAL_TEXT);
588     }
589
590     /**
591      * Sets the actual text (ActualText).
592      * 
593      * @param actualText the actual text
594      */
595     public void setActualText(String actualText)
596     {
597         this.getCOSDictionary().setString(COSName.ACTUAL_TEXT, actualText);
598     }
599
600     /**
601      * Returns the standard structure type, the actual structure type is mapped
602      * to in the role map.
603      * 
604      * @return the standard structure type
605      */
606     public String getStandardStructureType()
607     {
608         String type = this.getStructureType();
609         String mappedType;
610         while (true)
611         {
612             mappedType = this.getRoleMap().get(type);
613             if ((mappedType == null) || type.equals(mappedType))
614             {
615                 break;
616             }
617             type = mappedType;
618         }
619         return type;
620     }
621
622     /**
623      * Appends a marked-content sequence kid.
624      * 
625      * @param markedContent the marked-content sequence
626      */
627     public void appendKid(PDMarkedContent markedContent)
628     {
629         if (markedContent == null)
630         {
631             return;
632         }
633         this.appendKid(COSInteger.get(markedContent.getMCID()));
634     }
635
636     /**
637      * Appends a marked-content reference kid.
638      * 
639      * @param markedContentReference the marked-content reference
640      */
641     public void appendKid(PDMarkedContentReference markedContentReference)
642     {
643         this.appendObjectableKid(markedContentReference);
644     }
645
646     /**
647      * Appends an object reference kid.
648      * 
649      * @param objectReference the object reference
650      */
651     public void appendKid(PDObjectReference objectReference)
652     {
653         this.appendObjectableKid(objectReference);
654     }
655
656     /**
657      * Inserts a marked-content identifier kid before a reference kid.
658      * 
659      * @param markedContentIdentifier the marked-content identifier
660      * @param refKid the reference kid
661      */
662     public void insertBefore(COSInteger markedContentIdentifier, Object refKid)
663     {
664         this.insertBefore((COSBase) markedContentIdentifier, refKid);
665     }
666
667     /**
668      * Inserts a marked-content reference kid before a reference kid.
669      * 
670      * @param markedContentReference the marked-content reference
671      * @param refKid the reference kid
672      */
673     public void insertBefore(PDMarkedContentReference markedContentReference,
674         Object refKid)
675     {
676         this.insertObjectableBefore(markedContentReference, refKid);
677     }
678
679     /**
680      * Inserts an object reference kid before a reference kid.
681      * 
682      * @param objectReference the object reference
683      * @param refKid the reference kid
684      */
685     public void insertBefore(PDObjectReference objectReference, Object refKid)
686     {
687         this.insertObjectableBefore(objectReference, refKid);
688     }
689
690     /**
691      * Removes a marked-content identifier kid.
692      * 
693      * @param markedContentIdentifier the marked-content identifier
694      */
695     public void removeKid(COSInteger markedContentIdentifier)
696     {
697         this.removeKid((COSBase) markedContentIdentifier);
698     }
699
700     /**
701      * Removes a marked-content reference kid.
702      * 
703      * @param markedContentReference the marked-content reference
704      */
705     public void removeKid(PDMarkedContentReference markedContentReference)
706     {
707         this.removeObjectableKid(markedContentReference);
708     }
709
710     /**
711      * Removes an object reference kid.
712      * 
713      * @param objectReference the object reference
714      */
715     public void removeKid(PDObjectReference objectReference)
716     {
717         this.removeObjectableKid(objectReference);
718     }
719
720
721     /**
722      * Returns the structure tree root.
723      * 
724      * @return the structure tree root
725      */
726     private PDStructureTreeRoot getStructureTreeRoot()
727     {
728         PDStructureNode parent = this.getParent();
729         while (parent instanceof PDStructureElement)
730         {
731             parent = ((PDStructureElement) parent).getParent();
732         }
733         if (parent instanceof PDStructureTreeRoot)
734         {
735             return (PDStructureTreeRoot) parent;
736         }
737         return null;
738     }
739
740     /**
741      * Returns the role map.
742      * 
743      * @return the role map
744      */
745     private Map<String, String> getRoleMap()
746     {
747         PDStructureTreeRoot root = this.getStructureTreeRoot();
748         if (root != null)
749         {
750             return root.getRoleMap();
751         }
752         return null;
753     }
754
755 }