package org.apache.fop.fo;
// Java
+import java.util.Map;
import java.util.HashMap;
import org.xml.sax.Attributes;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.PropertyMaker;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
/**
* Class containing the collection of properties for a given FObj.
*/
private String namespace = "";
private FObj fobj = null;
+ private Log log = LogFactory.getLog(PropertyList.class);
+
+ /**
+ * Cache for properties looked up via maker.findProperty
+ * with bTryInherit == true
+ */
+ private Map cache = new HashMap();
+
/**
* Basic constructor.
* @param parentPropertyList the PropertyList belonging to the new objects
return null;
}
+ /**
+ * Wrapper around PropertyMaker.findProperty using the cache;
+ * use this method only if bTryInherit == true.
+ * The propertyMaker parameter is there
+ * to avoid repeated lookup of the maker
+ * in an alternating sequence of calls
+ * between findProperty and maker.findProperty.
+ * This would not be valid for FO elements
+ * which have their own list of property makers,
+ * see findMaker(propId).
+ * @param propId the ID of the property
+ * @param propertyMaker the maker of the property
+ * @return the cached property value
+ */
+ public Property findProperty (int propId, PropertyMaker propertyMaker)
+ throws FOPException {
+ Property p;
+ if (isInCache(propId)) {
+ p = getFromCache(propId);
+ } else {
+ p = propertyMaker.findProperty(this, true);
+ addToCache(propId, p);
+ }
+ return p;
+ }
+ /**
+ * Add a property value to the cache.
+ * The cached value may be null,
+ * meaning that no property value has been specified by the user
+ * on this FO element or, in the case of inheritable properties,
+ * on an ancester FO element.
+ * @param propId the ID of the property
+ * @param prop the property value being cached
+ */
+ private void addToCache(int propId, Property prop) {
+ String propertyName = FOPropertyMapping.getPropertyName(propId);
+ log.trace("PropertyList.addToCache: "
+ + propertyName + ", " + getFObj().getName());
+ cache.put(new Integer(propId), prop);
+ }
+
+ /**
+ * Check whether a property is in the cache.
+ * The presence of a key for a property
+ * means that a value for this property has been cached.
+ * @return whether a property is in the cache
+ */
+ public boolean isInCache(int propId) {
+ // Uncomment one or the other to use/not use the cache
+ return cache.containsKey(new Integer(propId));
+ // return false;
+ }
+
+ /**
+ * Retrieve a property from the cache
+ * @param propId the ID of the property
+ * @return the cached property value
+ */
+ public Property getFromCache(int propId) {
+ Property prop;
+ String propertyName = FOPropertyMapping.getPropertyName(propId);
+ prop = (Property) cache.get(new Integer(propId));
+ log.trace("PropertyList.getFromCache: "
+ + propertyName + ", " + getFObj().getName());
+ return prop;
+ }
/**
* Return the "nearest" specified value for the given property.
* isn't the right type for this compound property.
* @param p The Property object return by the expression parser
* @param propertyList The PropertyList object being built for this FO.
- * @param fo The current FO whose properties are being set.
+ * @param fo The parent FO for the FO whose property is being made.
* @return A Property of the correct type or null if the parsed value
* can't be converted to the correct type.
* @throws FOPException for invalid or inconsistent FO input
* Create a Property object from an attribute specification.
* @param propertyList The PropertyList object being built for this FO.
* @param value The attribute value.
- * @param fo The current FO whose properties are being set.
+ * @param fo The parent FO for the FO whose property is being made.
* @return The initialized Property object.
* @throws FOPException for invalid or inconsistent FO input
*/
* @param subpropId The Constants ID of the subproperty (component)
* whose value is specified.
* @param propertyList The propertyList being built.
- * @param fo The FO whose properties are being set.
+ * @param fo The parent FO for the FO whose property is being made.
* @param value the value of the
* @return baseProp (or if null, a new compound property object) with
* the new subproperty added
for (int i = 0; i < Constants.COMPOUND_COUNT; i++) {
PropertyMaker submaker = subproperties[i];
if (submaker != null) {
- Property subprop = submaker.make(propertyList, submaker.defaultValue, parentFO);
+ Property subprop = submaker.make(propertyList);
data.setComponent(submaker.getPropId() & Constants.COMPOUND_MASK, subprop, true);
}
}
import org.apache.fop.fo.expr.PropertyInfo;
import org.apache.fop.fo.expr.PropertyParser;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
/**
* Base class for all property makers
protected Property defaultProperty;
protected CorrespondingPropertyMaker corresponding;
+ private Log log = LogFactory.getLog(PropertyMaker.class);
+
/**
* @return the name of the property for this Maker
*/
* we try to compute it from the corresponding relative property: this
* happens in computeProperty.
*/
- protected Property findProperty(PropertyList propertyList,
+ public Property findProperty(PropertyList propertyList,
boolean bTryInherit)
throws FOPException
{
Property p = null;
+
+ log.trace("PropertyMaker.findProperty: "
+ + FOPropertyMapping.getPropertyName(propId)
+ + ", " + propertyList.getFObj().getName());
if (corresponding != null && corresponding.isCorrespondingForced(propertyList)) {
p = corresponding.compute(propertyList);
// else inherit (if has parent and is inheritable)
PropertyList parentPropertyList = propertyList.getParentPropertyList();
if (parentPropertyList != null && isInherited()) {
- p = findProperty(parentPropertyList, true);
+ if (!contextDep) {
+ // use the cache
+ p = parentPropertyList.findProperty(propId, this);
+ } else {
+ p = findProperty(parentPropertyList, bTryInherit);
+ }
}
}
}
boolean bTryInherit, boolean bTryDefault)
throws FOPException
{
- Property p = findProperty(propertyList, bTryInherit);
+ Property p;
+
+ if (!contextDep && bTryInherit) {
+ // use the cache
+ p = propertyList.findProperty(propId, this);
+ } else {
+ p = findProperty(propertyList, bTryInherit);
+ }
+
if (p == null && bTryDefault) { // default value for this FO!
try {
p = make(propertyList);
*/
public Property make(PropertyList propertyList) throws FOPException {
if (defaultProperty != null) {
+ log.trace("PropertyMaker.make: reusing defaultProperty, "
+ + FOPropertyMapping.getPropertyName(propId));
return defaultProperty;
}
+ log.trace("PropertyMaker.make: making default property value, "
+ + FOPropertyMapping.getPropertyName(propId)
+ + ", " + propertyList.getFObj().getName());
Property p = make(propertyList, defaultValue, propertyList.getParentFObj());
if (!contextDep) {
defaultProperty = p;
* Create a Property object from an attribute specification.
* @param propertyList The PropertyList object being built for this FO.
* @param value The attribute value.
- * @param fo The current FO whose properties are being set.
+ * @param fo The parent FO for the FO whose property is being made.
* @return The initialized Property object.
* @throws FOPException for invalid or inconsistent FO input
*/
* @param subpropId The Constants ID of the subproperty (component)
* whose value is specified.
* @param propertyList The propertyList being built.
- * @param fo The FO whose properties are being set.
+ * @param fo The parent FO for the FO whose property is being made.
* @param value the value of the
* @return baseProp (or if null, a new compound property object) with
* the new subproperty added
* It is overridden by subclasses.
* @param p The Property object return by the expression parser
* @param propertyList The PropertyList object being built for this FO.
- * @param fo The current FO whose properties are being set.
+ * @param fo The parent FO for the FO whose property is being made.
* @return A Property of the correct type or null if the parsed value
* can't be converted to the correct type.
* @throws FOPException for invalid or inconsistent FO input
* @param p property whose datatype should be converted
* @param propertyList collection of properties. (TODO: explain why
* this is needed, or remove it from the signature.)
- * @param fo the FObj to which this property is attached. (TODO: explain
+ * @param fo The parent FO for the FO whose property is being made.
* why this is needed, or remove it from the signature).
* @return an Property with the appropriate datatype used
*/
return null;
}
}
-}
\ No newline at end of file
+}
*/
protected void doLayout() {
+ log.debug("Starting layout");
// this should be done another way
makeNewPage(false, false);
createBodyMainReferenceArea();
}
}
pageCount--;
+ log.debug("Ending layout");
}
/**