/*
 * 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: RelativeNumericProperty.java 1610839 2014-07-15 20:25:58Z vhennebert $ */

package org.apache.fop.fo.expr;

import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.Numeric;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.TableColLength;
import org.apache.fop.util.CompareUtil;


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.
/** * 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 Length {
ADDITION
/** ADDITION */
public static final int ADDITION = 1;
SUBTRACTION
/** SUBTRACTION */
public static final int SUBTRACTION = 2;
MULTIPLY
/** MULTIPLY */
public static final int MULTIPLY = 3;
DIVIDE
/** DIVIDE */
public static final int DIVIDE = 4;
MODULO
/** MODULO */
public static final int MODULO = 5;
NEGATE
/** NEGATE */
public static final int NEGATE = 6;
ABS
/** ABS */
public static final int ABS = 7;
MAX
/** MAX */
public static final int MAX = 8;
MIN
/** MIN */
public static final int MIN = 9; // Used in the toString() method, indexed by operation id. private static String operations = " +-*/%";
The operation identifier.
/** * The operation identifier. */
private int operation;
The first (or only) operand.
/** * The first (or only) operand. */
private Numeric op1;
The second operand.
/** * The second operand. */
private Numeric op2;
The dimension of the result.
/** * The dimension of the result. */
private int dimension;
Constructor for a two argument operation.
Params:
  • operation – the operation opcode: ADDITION, SUBTRACTION, ...
  • op1 – the first operand.
  • op2 – the second operand
/** * 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.
Params:
  • operation – the operation opcode: NEGATE, ABS
  • op – the operand.
/** * 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.
Params:
  • context – Evaluation context
Throws:
Returns:the resolved Numeric corresponding to the value of the expression
/** * Return a resolved (calculated) Numeric with the value of the expression. * @param context Evaluation context * @return the resolved {@link Numeric} corresponding to the value of the expression * @throws PropertyException when an exception occur during evaluation. */
private Numeric getResolved(PercentBaseContext context) throws PropertyException { 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. {@inheritDoc}
/** * Return the resolved (calculated) value of the expression. * {@inheritDoc} */
public double getNumericValue() { try { return getResolved(null).getNumericValue(null); } catch (PropertyException pe) { throw new RuntimeException(pe); } }
{@inheritDoc}
/** * {@inheritDoc} */
public double getNumericValue(PercentBaseContext context) { try { return getResolved(context).getNumericValue(context); } catch (PropertyException pe) { throw new RuntimeException(pe); } }
Return the dimension of the expression
Returns:numeric value as dimension
/** * Return the dimension of the expression * @return numeric value as dimension */
public int getDimension() { return dimension; }
Return false since an expression is only created when there is relative numerics involved.
Returns:true if expression is absolute
/** * Return false since an expression is only created when there is relative * numerics involved. * @return true if expression is absolute */
public boolean isAbsolute() { return false; }
Cast this numeric as a Length.
Returns:numeric value as length
/** * Cast this numeric as a Length. * @return numeric value as length */
@Override public Length getLength() { if (dimension == 1) { return this; } log.error("Can't create length with dimension " + dimension); return null; }
Returns:numeric value
/** @return numeric value */
@Override public Numeric getNumeric() { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public int getValue() { return (int) getNumericValue(); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getValue(PercentBaseContext context) { return (int) getNumericValue(context); }
Return the number of table units which are included in this length specification. This will always be 0 unless the property specification used the proportional-column-width() function (only on table column FOs).

If this value is not 0, the actual value of the Length cannot be known without looking at all of the columns in the table to determine the value of a "table-unit".

Returns:The number of table units which are included in this length specification.
/** * Return the number of table units which are included in this length * specification. This will always be 0 unless the property specification * used the proportional-column-width() function (only on table column FOs). * <p> * If this value is not 0, the actual value of the Length cannot be known * without looking at all of the columns in the table to determine the value * of a "table-unit". * * @return The number of table units which are included in this length * specification. */
public double getTableUnits() { double tu1 = 0.0; double tu2 = 0.0; if (op1 instanceof RelativeNumericProperty) { tu1 = ((RelativeNumericProperty) op1).getTableUnits(); } else if (op1 instanceof TableColLength) { tu1 = ((TableColLength) op1).getTableUnits(); } if (op2 instanceof RelativeNumericProperty) { tu2 = ((RelativeNumericProperty) op2).getTableUnits(); } else if (op2 instanceof TableColLength) { tu2 = ((TableColLength) op2).getTableUnits(); } if (tu1 != 0.0 && tu2 != 0.0) { switch (operation) { case ADDITION: return tu1 + tu2; case SUBTRACTION: return tu1 - tu2; case MULTIPLY: return tu1 * tu2; case DIVIDE: return tu1 / tu2; case MODULO: return tu1 % tu2; case MIN: return Math.min(tu1, tu2); case MAX: return Math.max(tu1, tu2); default: assert false; } } else if (tu1 != 0.0) { switch (operation) { case NEGATE: return -tu1; case ABS: return Math.abs(tu1); default: return tu1; } } else if (tu2 != 0.0) { return tu2; } return 0.0; }
Return a string represention of the expression. Only used for debugging.
Returns:the string representation.
/** * Return a string represention of the expression. Only used for debugging. * @return the string representation. */
@Override 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 + ")"; default: return "unknown operation " + operation; } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + dimension; result = prime * result + CompareUtil.getHashCode(op1); result = prime * result + CompareUtil.getHashCode(op2); result = prime * result + operation; return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof RelativeNumericProperty)) { return false; } RelativeNumericProperty other = (RelativeNumericProperty) obj; return dimension == other.dimension && CompareUtil.equal(op1, other.op1) && CompareUtil.equal(op2, other.op2) && operation == other.operation; } }