001: /*
002: * Copyright (c) 2007, intarsys consulting GmbH
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * - Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * - Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * - Neither the name of intarsys nor the names of its contributors may be used
015: * to endorse or promote products derived from this software without specific
016: * prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028: * POSSIBILITY OF SUCH DAMAGE.
029: */
030: package de.intarsys.pdf.pd;
031:
032: import java.util.ArrayList;
033: import java.util.List;
034:
035: import de.intarsys.pdf.cos.COSBasedObject;
036: import de.intarsys.pdf.cos.COSDictionary;
037: import de.intarsys.pdf.cos.COSName;
038: import de.intarsys.pdf.cos.COSObject;
039:
040: /**
041: * Factoring out the commonalities between the PDOutline and PDOutlineItem.
042: */
043: public abstract class PDOutlineNode extends PDObject {
044: /**
045: * The meta class implementation
046: */
047: public static class MetaClass extends PDObject.MetaClass {
048: protected MetaClass(Class instanceClass) {
049: super (instanceClass);
050: }
051:
052: public Class getRootClass() {
053: return PDOutlineNode.class;
054: }
055:
056: protected COSBasedObject.MetaClass doDetermineClass(
057: COSObject object) {
058: if (object instanceof COSDictionary) {
059: COSDictionary dict = (COSDictionary) object;
060: COSName type = dict.get(PDObject.DK_Type).asName();
061: if (PDOutline.CN_Type_Outlines.equals(type)) {
062: return PDOutline.META;
063: }
064: if (dict.get(PDOutlineItem.DK_Parent).isNull()
065: && dict.get(PDOutlineItem.DK_Title).isNull()) {
066: return PDOutline.META;
067: }
068: return PDOutlineItem.META;
069: }
070: return super .doDetermineClass(object);
071: }
072: }
073:
074: /** The meta class instance */
075: public static final MetaClass META = new MetaClass(MetaClass.class
076: .getDeclaringClass());
077:
078: public static final COSName DK_First = COSName.constant("First");
079:
080: public static final COSName DK_Last = COSName.constant("Last");
081:
082: public static final COSName DK_Count = COSName.constant("Count");
083:
084: protected PDOutlineNode(COSObject object) {
085: super (object);
086: }
087:
088: /**
089: * The list of all child nodes for this.
090: *
091: * @return The list of all child nodes for this.
092: */
093: public List getChildren() {
094: List result = new ArrayList();
095: PDOutlineItem current = getFirst();
096: while (current != null) {
097: result.add(current);
098: current = current.getNext();
099: }
100: return result;
101: }
102:
103: /**
104: * The number of child elements.
105: *
106: * @return The number of child elements.
107: */
108: public int getCount() {
109: return getFieldInt(DK_Count, 0);
110: }
111:
112: protected void setCount(int newCount) {
113: setFieldInt(DK_Count, newCount);
114: }
115:
116: /**
117: * The first child element in the linked list of children.
118: *
119: * @return The first child element in the linked list of children.
120: */
121: public PDOutlineItem getFirst() {
122: return (PDOutlineItem) PDOutlineItem.META
123: .createFromCos(cosGetField(DK_First));
124: }
125:
126: protected void setFirst(PDOutlineItem first) {
127: setFieldObject(DK_First, first);
128: }
129:
130: protected void setLast(PDOutlineItem last) {
131: setFieldObject(DK_Last, last);
132: }
133:
134: /**
135: * The last child element in the linked list of children.
136: *
137: * @return The last child element in the linked list of children.
138: */
139: public PDOutlineItem getLast() {
140: return (PDOutlineItem) PDOutlineItem.META
141: .createFromCos(cosGetField(DK_Last));
142: }
143:
144: /**
145: * <code>true</code> if this is the outline (root element) itself.
146: *
147: * @return <code>true</code> if this is the outline (root element) itself.
148: */
149: public boolean isOutline() {
150: return false;
151: }
152:
153: /**
154: * Add a new {@link PDOutlineItem}.
155: *
156: * @param newItem
157: * The new item to be inserted at the end.
158: */
159: public void addItem(PDOutlineItem newItem) {
160: int newCount = getCount() + 1;
161: setCount(newCount);
162: PDOutlineItem first = getFirst();
163: if (first == null) {
164: setFirst(newItem);
165: }
166: PDOutlineItem last = getLast();
167: if (last != null) {
168: last.setNext(newItem);
169: newItem.setPrev(last);
170: }
171: setLast(newItem);
172: newItem.setParent(this );
173: }
174:
175: /**
176: * Remove a {@link PDOutlineItem} from this.
177: *
178: * @param pItem
179: * The item to be removed.
180: * @return <code>true</code> if the item was removed.
181: */
182: public boolean removeItem(PDOutlineItem pItem) {
183: if (pItem.getParent() != this ) {
184: return false;
185: }
186: int newCount = getCount() - 1;
187: setCount(newCount);
188: if (pItem.getPrev() != null) {
189: pItem.getPrev().setNext(pItem.getNext());
190: }
191: if (pItem.getNext() != null) {
192: pItem.getNext().setPrev(pItem.getPrev());
193: }
194: if (newCount == 0) {
195: setFirst(null);
196: setLast(null);
197: } else {
198: if (getFirst() == pItem) {
199: setFirst(pItem.getNext());
200: }
201: if (getLast() == pItem) {
202: setLast(pItem.getPrev());
203: }
204: }
205: pItem.setParent(null);
206: return true;
207: }
208: }
|