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.content;
031:
032: import java.util.Arrays;
033: import java.util.Iterator;
034: import de.intarsys.pdf.cos.COSName;
035: import de.intarsys.pdf.cos.COSObject;
036:
037: /**
038: * Represents the operations that make up a content stream.
039: *
040: * <p>
041: * The content stream is a sequence of operations, with any operation beeing a
042: * list of operands followed by the operator.
043: * </p>
044: */
045: public class CSOperation {
046: static public final COSName OPERAND_Tx = COSName.constant("Tx"); //$NON-NLS-1$
047:
048: /**
049: * More efficient internal representation of operator
050: */
051: private byte[] operatorToken;
052:
053: /** The operands to the operator */
054: private COSObject[] operands;
055:
056: public CSOperation(CSOperator operator) {
057: this (operator, new COSObject[0]);
058: }
059:
060: public CSOperation(CSOperator operator, COSObject[] operands) {
061: super ();
062: this .operatorToken = operator.getToken();
063: this .operands = operands;
064: }
065:
066: public CSOperation(byte[] operatorToken, COSObject[] operands) {
067: super ();
068: this .operatorToken = operatorToken;
069: this .operands = operands;
070: }
071:
072: /**
073: * <code>true</code> if this is a "begin marked content" operation with
074: * the operand <code>mark</code> (or any operation when mark is null).
075: *
076: * @param mark
077: * The requested operand to the operation.
078: *
079: * @return <code>true</code> if this is a "begin marked content" operation
080: * with the operand <code>mark</code>.
081: */
082: public boolean isOpBeginMarkedContent(COSName mark) {
083: if (matchesOperator(CSOperators.CSO_BMC)) {
084: if ((mark == null) || (operandSize() == 0)) {
085: return true;
086: }
087: COSObject operand = getOperand(0);
088: if (operand instanceof COSName
089: && ((COSName) operand).equals(mark)) {
090: return true;
091: }
092: }
093: return false;
094: }
095:
096: /**
097: * <code>true</code> if this is a "end marked content" operation.
098: *
099: * @return <code>true</code> if this is a "end marked content" operation
100: */
101: public boolean isOpEndMarkedContent() {
102: if (matchesOperator(CSOperators.CSO_EMC)) {
103: return true;
104: }
105: return false;
106: }
107:
108: /**
109: * The operand at index <code>i</code>.
110: *
111: * @param i
112: * The index of the perand in the operand's list.
113: *
114: * @return The operand at index <code>i</code>.
115: */
116: public COSObject getOperand(int i) {
117: return operands[i];
118: }
119:
120: /**
121: * Set operand at index <code>i</code> to <code>objec</code>.
122: *
123: * @param i
124: * The index of the perand in the operand's list.
125: * @param object
126: * the operand object
127: *
128: * @return The previous operand at index <code>i</code>.
129: */
130: public COSObject setOperand(int i, COSObject object) {
131: COSObject old = operands[i];
132: operands[i] = object;
133: return old;
134: }
135:
136: /**
137: * The iterator over all operands.
138: *
139: * @return The iterator over all operands.
140: */
141: public Iterator getOperands() {
142: return Arrays.asList(operands).iterator();
143: }
144:
145: /**
146: * The operator of the operation.
147: *
148: * @return The operator of the operation.
149: */
150: public CSOperator getOperator() {
151: return new CSOperator(operatorToken);
152: }
153:
154: public byte[] getOperatorToken() {
155: return operatorToken;
156: }
157:
158: /**
159: * Add an operand at the end of the current operand list.
160: *
161: * @param object
162: * The new operand to add.
163: */
164: public void addOperand(COSObject object) {
165: COSObject[] newOperands = new COSObject[operands.length + 1];
166: System.arraycopy(operands, 0, newOperands, 0, operands.length);
167: newOperands[newOperands.length - 1] = object;
168: operands = newOperands;
169: }
170:
171: /**
172: * Answer <code>true</code> if an operator is already defined.
173: *
174: * @return Answer <code>true</code> if an operator is already defined.
175: */
176: public boolean hasOperator() {
177: return operatorToken != null;
178: }
179:
180: /**
181: * Answer <code>true</code> if this operator's name matches the token
182: * <code>other</code>.
183: *
184: * @param other
185: * token to check against the operators name.
186: *
187: * @return Answer <code>true</code> if this operator's name matches the
188: * token <code>other</code>.
189: */
190: public boolean matchesOperator(CSOperator other) {
191: return Arrays.equals(operatorToken, ((CSOperator) other)
192: .getToken());
193: }
194:
195: /**
196: * Answer the number of operands.
197: *
198: * @return the number of operands.
199: */
200: public int operandSize() {
201: return operands.length;
202: }
203:
204: /*
205: * (non-Javadoc)
206: *
207: * @see java.lang.Object#toString()
208: */
209: public String toString() {
210: StringBuilder sb = new StringBuilder();
211: for (Iterator it = getOperands(); it.hasNext();) {
212: COSObject operand = (COSObject) it.next();
213: sb.append(operand.toString());
214: sb.append(" "); //$NON-NLS-1$
215: }
216: sb.append(new String(operatorToken));
217: return sb.toString();
218: }
219: }
|