blob: 5c52ebe174eccfbf4c29bbed0a7c9d986032389b [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
package org.apache.fop.fo.expr;
import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.datatypes.Numeric;
import org.apache.fop.fo.properties.Property;
/**
* This class represent a node in a property expression tree.
* It is created when an operation involve relative expression and is used
* to delay evaluation of the operation until the time where getNumericValue()
* or getValue() is called.
*/
public class RelativeNumericProperty extends Property implements Numeric, Length {
public static final int ADDITION = 1;
public static final int SUBTRACTION = 2;
public static final int MULTIPLY = 3;
public static final int DIVIDE = 4;
public static final int MODULO = 5;
public static final int NEGATE = 6;
public static final int ABS = 7;
public static final int MAX = 8;
public static final int MIN = 9;
// Used in the toString() method, indexed by operation id.
private static String operations = " +-*/%";
/**
* The operation identifier.
*/
private int operation;
/**
* The first (or only) operand.
*/
private Numeric op1;
/**
* The second operand.
*/
private Numeric op2;
/**
* The dimension of the result.
*/
private int dimension;
/**
* Constructor for a two argument operation.
* @param operation the operation opcode: ADDITION, SUBTRACTION, ...
* @param op1 the first operand.
* @param op2 the second operand
*/
public RelativeNumericProperty(int operation, Numeric op1, Numeric op2) {
this.operation = operation;
this.op1 = op1;
this.op2 = op2;
// Calculate the dimension. We can do now.
switch (operation) {
case MULTIPLY:
dimension = op1.getDimension() + op2.getDimension();
break;
case DIVIDE:
dimension = op1.getDimension() - op2.getDimension();
break;
default:
dimension = op1.getDimension();
}
}
/**
* Constructor for a one argument operation.
* @param operation the operation opcode: NEGATE, ABS
* @param op the operand.
*/
public RelativeNumericProperty(int operation, Numeric op) {
this.operation = operation;
this.op1 = op;
this.dimension = op.getDimension();
}
/**
* Return a resolved (calculated) Numeric with the value of the expression.
* @param context Evaluation context
* @throws PropertyException when an exception occur during evaluation.
*/
private Numeric getResolved(PercentBaseContext context) throws PropertyException {
Numeric n;
switch (operation) {
case ADDITION:
return NumericOp.addition2(op1, op2, context);
case SUBTRACTION:
return NumericOp.subtraction2(op1, op2, context);
case MULTIPLY:
return NumericOp.multiply2(op1, op2, context);
case DIVIDE:
return NumericOp.divide2(op1, op2, context);
case MODULO:
return NumericOp.modulo2(op1, op2, context);
case NEGATE:
return NumericOp.negate2(op1, context);
case ABS:
return NumericOp.abs2(op1, context);
case MAX:
return NumericOp.max2(op1, op2, context);
case MIN:
return NumericOp.min2(op1, op2, context);
default:
throw new PropertyException("Unknown expr operation " + operation);
}
}
/**
* Return the resolved (calculated) value of the expression.
* @see org.apache.fop.datatypes.Numeric#getNumericValue()
*/
public double getNumericValue() throws PropertyException {
return getResolved(null).getNumericValue(null);
}
/**
* @see org.apache.fop.datatypes.Numeric#getNumericValue(PercentBaseContext)
*/
public double getNumericValue(PercentBaseContext context) throws PropertyException {
return getResolved(context).getNumericValue(context);
}
/**
* Return the dimension of the expression
*/
public int getDimension() {
return dimension;
}
/**
* Return false since an expression is only created when there is relative
* numerics involved.
*/
public boolean isAbsolute() {
return false;
}
/**
* Cast this numeric as a Length.
*/
public Length getLength() {
if (dimension == 1) {
return this;
}
log.error("Can't create length with dimension " + dimension);
return null;
}
public Numeric getNumeric() {
return this;
}
/**
* @see org.apache.fop.datatypes.Numeric#getValue()
*/
public int getValue() {
try {
return (int) getNumericValue();
} catch (PropertyException exc) {
log.error(exc);
}
return 0;
}
/**
* @see org.apache.fop.datatypes.Numeric#getValue(PercentBaseContext)
*/
public int getValue(PercentBaseContext context) {
try {
return (int) getNumericValue(context);
} catch (PropertyException exc) {
log.error(exc);
}
return 0;
}
/**
* Return a string represention of the expression. Only used for debugging.
* @return the string representation.
*/
public String toString() {
switch (operation) {
case ADDITION: case SUBTRACTION:
case DIVIDE: case MULTIPLY: case MODULO:
return "(" + op1 + " " + operations.charAt(operation) + op2 + ")";
case NEGATE:
return "-" + op1;
case MAX:
return "max(" + op1 + ", " + op2 + ")";
case MIN:
return "min(" + op1 + ", " + op2 + ")";
case ABS:
return "abs(" + op1 + ")";
}
return "unknown operation " + operation;
}
}