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