All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.intarsys.pdf.cos.COSArray Maven / Gradle / Ivy

/*
 * Copyright (c) 2007, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.intarsys.pdf.cos;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * A COSArray represents an indexed collection of {@link COSDocumentElement}
 * instances.
 * 

* Using the standard access methods, always "dereferenced" {@link COSObject} * instances are returned. Use the "basic" falvor of methods to access the * optional {@link COSIndirectObject}. */ public class COSArray extends COSCompositeObject { /** * Create an empty {@link COSArray}. * * @return Create an empty {@link COSArray}. */ public static COSArray create() { return new COSArray(); } /** * Create an empty {@link COSArray} with a preallocated size. * * @return Create an empty {@link COSArray}. */ public static COSArray create(int size) { return new COSArray(size); } /** * Shortcut for fast creation of rectangle arrays * * @param a * @param b * @param c * @param d * @return a new COSArray */ public static COSArray createWith(float a, float b, float c, float d) { COSArray result = new COSArray(4); result.basicAddSilent(COSFixed.create(a)); result.basicAddSilent(COSFixed.create(b)); result.basicAddSilent(COSFixed.create(c)); result.basicAddSilent(COSFixed.create(d)); return result; } /** * Shortcut for fast creation of matrix arrays * * @param a * @param b * @param c * @param d * @param e * @param f * @return a new COSArray */ public static COSArray createWith(float a, float b, float c, float d, float e, float f) { COSArray result = new COSArray(6); result.basicAddSilent(COSFixed.create(a)); result.basicAddSilent(COSFixed.create(b)); result.basicAddSilent(COSFixed.create(c)); result.basicAddSilent(COSFixed.create(d)); result.basicAddSilent(COSFixed.create(e)); result.basicAddSilent(COSFixed.create(f)); return result; } /** the list of document elements contained */ private final List objects; protected COSArray() { super(); this.objects = new ArrayList(); } protected COSArray(int size) { super(); this.objects = new ArrayList(size); } protected COSArray(List objects) { super(); this.objects = objects; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#accept(de.intarsys.pdf.cos.ICOSObjectVisitor) */ @Override public java.lang.Object accept(ICOSObjectVisitor visitor) throws COSVisitorException { return visitor.visitFromArray(this); } /** * Add a {@link COSObject} to the collection. * *

* This method takes care of change propagation for incremental writing. *

* *

* this method should be used by the application level programmer to ensure * he deals not with references. *

* * @param object * the object to be added * * @return this */ public COSArray add(COSObject object) { willChange(this); basicAddPropagate(object); if (objectListeners != null) { triggerChanged(objects.size(), COSNull.NULL, object); } return this; } /** * Add a {@link COSObject} to the collection. * *

* This method takes care of change propagation for incremental writing. *

* *

* this method should be used by the application level programmer to ensure * he deals not with references. *

* * @param index * The index where to insert object * @param object * the object to be added * * @return this */ public COSArray add(int index, COSObject object) { willChange(this); basicAddPropagate(index, object); if (objectListeners != null) { triggerChanged(index, COSNull.NULL, object); } return this; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#getCOSArray() */ @Override public COSArray asArray() { return this; } /** * Add a document element (an object or a reference) to the collection. * *

* This method should only be used for low level programming (parser). *

* * @param element * the element to be added * * @return The receiver. */ protected COSArray basicAddPropagate(COSDocumentElement element) { COSObject dereferenced = element.dereference(); COSDocumentElement containable = element.containable(); willChange(dereferenced); ICOSContainer newContainer = containable.addContainer(this); objects.add(containable); dereferenced.triggerChanged(COSObject.SLOT_CONTAINER, null, newContainer); return this; } /** * add a document element (an object or a reference) to the collection. * *

* this method should only be used for low level programming (parser). *

* * @param index * The index where to insert object * @param element * the element to be added * * @return this */ protected COSArray basicAddPropagate(int index, COSDocumentElement element) { COSObject dereferenced = element.dereference(); COSDocumentElement containable = element.containable(); willChange(dereferenced); ICOSContainer newContainer = containable.addContainer(this); objects.add(index, containable); dereferenced.triggerChanged(COSObject.SLOT_CONTAINER, null, newContainer); return this; } /** * Add a document element (an object or a reference) to the collection. * *

* The change is not propagated. *

* This should not be used by the application level programmer. It is public * for package visibility reasons. * * * @param element * the element to be added * * @return The receiver. */ public COSArray basicAddSilent(COSDocumentElement element) { COSDocumentElement containable = element.containable(); containable.addContainer(this); objects.add(containable); return this; } /** * Remove all elements from the receiver. * */ protected void basicClearPropagate() { List oldObjects = new ArrayList(objects); objects.clear(); for (Iterator i = oldObjects.iterator(); i.hasNext();) { COSDocumentElement element = (COSDocumentElement) i.next(); COSObject dereferenced = element.dereference(); willChange(dereferenced); ICOSContainer newContainer = element.removeContainer(this); dereferenced.triggerChanged(COSObject.SLOT_CONTAINER, null, newContainer); } } /** * Get the {@link COSDocumentElement} (an object or a reference) from this * at the specified index. *

* This method should only be used for low level programming. * * @param index * The index into this * * @return Get the {@link COSDocumentElement} (an object or a reference) * from this at the specified index. */ public COSDocumentElement basicGet(int index) { return (COSDocumentElement) objects.get(index); } /** * The index within this where element can be found or -1. * * @param element * The element to be searched within this. * @return The index of element or -1 if nothing found. */ protected int basicIndexOf(COSDocumentElement element) { COSDocumentElement containable = element.containable(); int i = 0; for (Iterator it = basicIterator(); it.hasNext();) { COSDocumentElement current = (COSDocumentElement) it.next(); if (containable == current) { return i; } i++; } return -1; } /** * An iterator that returns all contained {@link COSDocumentElement} * instances without dereferencing. * *

* This should be used in low level programming. *

* * @return An iterator that returns all contained {@link COSDocumentElement} * instances without dereferencing. */ @Override public Iterator basicIterator() { return objects.iterator(); } /** * Remove otherElement from this. * * @param otherElement * The element to be removed. * @return true if element was removed. */ protected boolean basicRemovePropagate(COSDocumentElement otherElement) { COSObject dereferenced = otherElement.dereference(); COSDocumentElement containable = otherElement.containable(); for (Iterator i = basicIterator(); i.hasNext();) { COSDocumentElement element = (COSDocumentElement) i.next(); if (containable == element) { i.remove(); willChange(dereferenced); ICOSContainer newContainer = containable.removeContainer(this); dereferenced.triggerChanged(COSObject.SLOT_CONTAINER, null, newContainer); return true; } } return false; } /** * Remove element at index. * * @param index * The index within this to be removed. * @return The {@link COSDocumentElement} that was removed at the specified * index. */ protected COSDocumentElement basicRemovePropagate(int index) { COSDocumentElement removed = (COSDocumentElement) objects.remove(index); COSObject dereferenced = removed.dereference(); willChange(dereferenced); ICOSContainer newContainer = removed.removeContainer(this); dereferenced.triggerChanged(COSObject.SLOT_CONTAINER, null, newContainer); return removed; } /** * replace the object at index <i with element. * * @param i * the index * @param element * the object to put at the specified index * * @return The previously contained object */ protected COSDocumentElement basicSetPropagate(int i, COSDocumentElement element) { COSObject dereferenced = element.dereference(); COSDocumentElement containable = element.containable(); // willChange(dereferenced); ICOSContainer newContainer = containable.addContainer(this); COSDocumentElement oldContainable = (COSDocumentElement) objects.set(i, containable); dereferenced.triggerChanged(COSObject.SLOT_CONTAINER, null, newContainer); // if (oldContainable != containable) { COSObject oldDereferenced = oldContainable.dereference(); willChange(oldDereferenced); newContainer = oldContainable.removeContainer(this); oldDereferenced.triggerChanged(COSObject.SLOT_CONTAINER, null, newContainer); } return oldContainable; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#basicToString() */ @Override protected String basicToString() { return objects.toString(); } /** * Remove all elements from this. */ public void clear() { willChange(this); basicClearPropagate(); if (objectListeners != null) { triggerChanged(-1, null, null); } } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#copyBasic(de.intarsys.pdf.cos.COSDocument) */ @Override protected COSObject copyBasic() { return create(size()); } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#copyDeep(java.util.Map) */ @Override public COSObject copyDeep(Map copied) { COSArray result = (COSArray) super.copyDeep(copied); for (Iterator i = basicIterator(); i.hasNext();) { COSDocumentElement element = (COSDocumentElement) i.next(); COSObject copy = element.copyDeep(copied); result.basicAddSilent(copy); } return result; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#copyShallow() */ @Override public COSObject copyShallow() { COSArray result = (COSArray) super.copyShallow(); for (Iterator i = basicIterator(); i.hasNext();) { COSDocumentElement element = (COSDocumentElement) i.next(); result.basicAddSilent(element.copyShallowNested()); } return result; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#copyNet(java.util.Map) */ @Override protected COSObject copySubGraph(Map copied) { COSArray result = (COSArray) super.copySubGraph(copied); // for (Iterator i = basicIterator(); i.hasNext();) { // COSDocumentElement element = (COSDocumentElement) i.next(); // COSObject copy = null; // if (element.isReference()) { // copy = (COSObject) copied.get(element); // if (copy == null) { // if (value.hasNavigationPathTo(this)) { // copy = value.copySubGraph(copied); // } else { // copy = value; // copied.put(value.getIndirectObject(), copy); // } // } // } else { // copy = value.copySubGraph(copied); // } // result.basicAdd(copy); // } return result; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { return this.equals(o, new HashSet()); } @Override protected boolean equals(Object o, Set visited) { if (isIndirect()) { if (visited.contains(getIndirectObject())) { return true; } visited.add(getIndirectObject()); } if (this == o) { return true; } if (!(o instanceof COSArray)) { return false; } COSArray other = (COSArray) o; if (size() != other.size()) { return false; } Iterator iThis = this.basicIterator(); Iterator iOther = other.basicIterator(); for (; iThis.hasNext() && iOther.hasNext();) { COSDocumentElement eThis = (COSDocumentElement) iThis.next(); COSObject oThis = eThis.dereference(); COSDocumentElement eOther = (COSDocumentElement) iOther.next(); COSObject oOther = eOther.dereference(); if ((oThis == null) && (oOther != null)) { return false; } if (!oThis.equals(oOther, visited)) { return false; } } if (iThis.hasNext() || iOther.hasNext()) { return false; } return true; } /** * The {@link COSObject} at the given index. Any index outisde the valid * array range results in COSNull (compare Adobe Core ApI Reference). * * @param index * The index of the {@link COSObject} to select from this. * * @return The {@link COSObject} at the given index or {@link COSNull}. */ public COSObject get(int index) { try { return ((COSDocumentElement) objects.get(index)).dereference(); } catch (IndexOutOfBoundsException e) { return COSNull.NULL; } } /** * A copy of all COSObject's in this. * *

* Indirect objects and dangling references are handled by this method. *

* * @return A copy of all COSObject's in this. */ public List getObjects() { int size = size(); List result = new ArrayList(size); for (int i = 0; i < size; i++) { result.add(get(i)); } return result; } /** * ATTENTION: this implementation returns a hash code that does not remain * constant when manipulating the arrays content * * @see Object#hashCode() */ @Override public int hashCode() { int result = 17; for (Iterator iThis = this.basicIterator(); iThis.hasNext();) { COSDocumentElement oThis = (COSDocumentElement) iThis.next(); if (oThis.isReference()) { result = (result + oThis.hashCode()) * 34; } else if (((COSObject) oThis).isPrimitive()) { // do not descend result = (result + oThis.hashCode()) * 34; } else { result = (result + 17) * 34; } } return result; } /** * The index of object within this or -1 if not found. * * @param object * The object to be searched within this. * @return The index of object within this or -1 if not * found. */ public int indexOf(COSObject object) { return basicIndexOf(object); } /** * true if this.size() == 0. * * @return true if this.size() == 0. */ public boolean isEmpty() { return objects.size() == 0; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#iterator() */ @Override public java.util.Iterator iterator() { return new Iterator() { private int index = 0; private int size = size(); public boolean hasNext() { return index < size; } public Object next() { return get(index++); } public void remove() { throw new UnsupportedOperationException(); } }; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSCompositeObject#referenceIndirect(de.intarsys.pdf.cos.COSObject) */ @Override public COSIndirectObject referenceIndirect(COSObject object) { COSIndirectObject ref = super.referenceIndirect(object); int index = getObjects().indexOf(object); if (index >= 0) { objects.set(index, ref); } return ref; } /** * Remove object from this. If object is not * contained, nothing happens. * *

* This method cycles all elements which may cause heavy lazy loading. *

* * @param object * The object to remove from this. * @return true if object was removed. */ public boolean remove(COSObject object) { willChange(this); boolean result = basicRemovePropagate(object); if ((objectListeners != null) && result) { triggerChanged(-1, object, COSNull.NULL); } return result; } /** * Remove the object at index from the collection. * * @param index * The index of the object to remove from the collection. * @return The object previously stored at the index. */ public COSObject remove(int index) { willChange(this); COSDocumentElement element = basicRemovePropagate(index); COSObject object = element.dereference(); if (objectListeners != null) { triggerChanged(index, object, COSNull.NULL); } return object; } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSObject#restoreState(java.lang.Object) */ @Override public void restoreState(Object object) { super.restoreState(object); objects.clear(); objects.addAll(((COSArray) object).objects); if (objectListeners != null) { triggerChanged(-1, null, null); } } /* * (non-Javadoc) * * @see de.intarsys.tools.objectsession.ISaveStateSupport#saveState() */ public Object saveState() { COSArray result = new COSArray(new ArrayList(this.objects)); result.container = this.container.saveStateContainer(); return result; } /** * Replace the object at index i with object. * * @param i * The index * @param object * The object to put at the specified index * * @return The previuosly referenced object */ public COSObject set(int i, COSObject object) { willChange(this); COSDocumentElement element = basicSetPropagate(i, object); COSObject oldObject = element.dereference(); if (objectListeners != null) { triggerChanged(i, oldObject, object); } return oldObject; } /** * The number of elements in this. * * @return The number of elements in this. */ public int size() { return objects.size(); } public COSDocumentElement[] toArray() { return (COSDocumentElement[]) objects .toArray(new COSDocumentElement[objects.size()]); } protected void triggerChanged(int slot, COSObject oldValue, COSObject newValue) { if (objectListeners == null) { return; } Integer slotObject = new Integer(slot); for (Iterator it = objectListeners.iterator(); it.hasNext();) { ICOSObjectListener listener = (ICOSObjectListener) it.next(); listener.changed(this, slotObject, oldValue, newValue); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy