001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: RelativeNumericProperty.java 488960 2006-12-20 08:34:28Z spepping $ */
019:
020: package org.apache.fop.fo.expr;
021:
022: import org.apache.fop.datatypes.Length;
023: import org.apache.fop.datatypes.PercentBaseContext;
024: import org.apache.fop.datatypes.Numeric;
025: import org.apache.fop.fo.properties.Property;
026:
027: /**
028: * This class represent a node in a property expression tree.
029: * It is created when an operation involve relative expression and is used
030: * to delay evaluation of the operation until the time where getNumericValue()
031: * or getValue() is called.
032: */
033: public class RelativeNumericProperty extends Property implements
034: Numeric, Length {
035: public static final int ADDITION = 1;
036: public static final int SUBTRACTION = 2;
037: public static final int MULTIPLY = 3;
038: public static final int DIVIDE = 4;
039: public static final int MODULO = 5;
040: public static final int NEGATE = 6;
041: public static final int ABS = 7;
042: public static final int MAX = 8;
043: public static final int MIN = 9;
044:
045: // Used in the toString() method, indexed by operation id.
046: private static String operations = " +-*/%";
047:
048: /**
049: * The operation identifier.
050: */
051: private int operation;
052: /**
053: * The first (or only) operand.
054: */
055: private Numeric op1;
056: /**
057: * The second operand.
058: */
059: private Numeric op2;
060: /**
061: * The dimension of the result.
062: */
063: private int dimension;
064:
065: /**
066: * Constructor for a two argument operation.
067: * @param operation the operation opcode: ADDITION, SUBTRACTION, ...
068: * @param op1 the first operand.
069: * @param op2 the second operand
070: */
071: public RelativeNumericProperty(int operation, Numeric op1,
072: Numeric op2) {
073: this .operation = operation;
074: this .op1 = op1;
075: this .op2 = op2;
076: // Calculate the dimension. We can do now.
077: switch (operation) {
078: case MULTIPLY:
079: dimension = op1.getDimension() + op2.getDimension();
080: break;
081: case DIVIDE:
082: dimension = op1.getDimension() - op2.getDimension();
083: break;
084: default:
085: dimension = op1.getDimension();
086: }
087: }
088:
089: /**
090: * Constructor for a one argument operation.
091: * @param operation the operation opcode: NEGATE, ABS
092: * @param op the operand.
093: */
094: public RelativeNumericProperty(int operation, Numeric op) {
095: this .operation = operation;
096: this .op1 = op;
097: this .dimension = op.getDimension();
098: }
099:
100: /**
101: * Return a resolved (calculated) Numeric with the value of the expression.
102: * @param context Evaluation context
103: * @throws PropertyException when an exception occur during evaluation.
104: */
105: private Numeric getResolved(PercentBaseContext context)
106: throws PropertyException {
107: switch (operation) {
108: case ADDITION:
109: return NumericOp.addition2(op1, op2, context);
110: case SUBTRACTION:
111: return NumericOp.subtraction2(op1, op2, context);
112: case MULTIPLY:
113: return NumericOp.multiply2(op1, op2, context);
114: case DIVIDE:
115: return NumericOp.divide2(op1, op2, context);
116: case MODULO:
117: return NumericOp.modulo2(op1, op2, context);
118: case NEGATE:
119: return NumericOp.negate2(op1, context);
120: case ABS:
121: return NumericOp.abs2(op1, context);
122: case MAX:
123: return NumericOp.max2(op1, op2, context);
124: case MIN:
125: return NumericOp.min2(op1, op2, context);
126: default:
127: throw new PropertyException("Unknown expr operation "
128: + operation);
129: }
130: }
131:
132: /**
133: * Return the resolved (calculated) value of the expression.
134: * @see org.apache.fop.datatypes.Numeric#getNumericValue()
135: */
136: public double getNumericValue() throws PropertyException {
137: return getResolved(null).getNumericValue(null);
138: }
139:
140: /**
141: * @see org.apache.fop.datatypes.Numeric#getNumericValue(PercentBaseContext)
142: */
143: public double getNumericValue(PercentBaseContext context)
144: throws PropertyException {
145: return getResolved(context).getNumericValue(context);
146: }
147:
148: /**
149: * Return the dimension of the expression
150: */
151: public int getDimension() {
152: return dimension;
153: }
154:
155: /**
156: * Return false since an expression is only created when there is relative
157: * numerics involved.
158: */
159: public boolean isAbsolute() {
160: return false;
161: }
162:
163: /**
164: * Cast this numeric as a Length.
165: */
166: public Length getLength() {
167: if (dimension == 1) {
168: return this ;
169: }
170: log.error("Can't create length with dimension " + dimension);
171: return null;
172: }
173:
174: public Numeric getNumeric() {
175: return this ;
176: }
177:
178: /**
179: * @see org.apache.fop.datatypes.Numeric#getValue()
180: */
181: public int getValue() {
182: try {
183: return (int) getNumericValue();
184: } catch (PropertyException exc) {
185: log.error(exc);
186: }
187: return 0;
188: }
189:
190: /**
191: * @see org.apache.fop.datatypes.Numeric#getValue(PercentBaseContext)
192: */
193: public int getValue(PercentBaseContext context) {
194: try {
195: return (int) getNumericValue(context);
196: } catch (PropertyException exc) {
197: log.error(exc);
198: }
199: return 0;
200: }
201:
202: /**
203: * Return a string represention of the expression. Only used for debugging.
204: * @return the string representation.
205: */
206: public String toString() {
207: switch (operation) {
208: case ADDITION:
209: case SUBTRACTION:
210: case DIVIDE:
211: case MULTIPLY:
212: case MODULO:
213: return "(" + op1 + " " + operations.charAt(operation) + op2
214: + ")";
215: case NEGATE:
216: return "-" + op1;
217: case MAX:
218: return "max(" + op1 + ", " + op2 + ")";
219: case MIN:
220: return "min(" + op1 + ", " + op2 + ")";
221: case ABS:
222: return "abs(" + op1 + ")";
223: }
224: return "unknown operation " + operation;
225: }
226: }
|