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: CompoundPropertyMaker.java 426576 2006-07-28 15:44:37Z jeremias $ */
019:
020: package org.apache.fop.fo.properties;
021:
022: import org.apache.fop.datatypes.CompoundDatatype;
023: import org.apache.fop.fo.Constants;
024: import org.apache.fop.fo.FObj;
025: import org.apache.fop.fo.PropertyList;
026: import org.apache.fop.fo.expr.PropertyException;
027:
028: /**
029: * @author me
030: *
031: * To change the template for this generated type comment go to
032: * Window - Preferences - Java - Code Generation - Code and Comments
033: */
034: /**
035: * This class extends Property.Maker with support for sub-properties.
036: */
037: public class CompoundPropertyMaker extends PropertyMaker {
038: /**
039: * The list of subproperty makers supported by this compound maker.
040: */
041: private PropertyMaker[] subproperties = new PropertyMaker[Constants.COMPOUND_COUNT];
042:
043: /**
044: * The first subproperty maker which has a setByShorthand of true.
045: */
046: private PropertyMaker shorthandMaker = null;
047:
048: /**
049: * Construct an instance of a CompoundPropertyMaker for the given property.
050: * @param propId The Constant ID of the property to be made.
051: */
052: public CompoundPropertyMaker(int propId) {
053: super (propId);
054: }
055:
056: /**
057: * @see org.apache.fop.fo.properties.PropertyMaker#useGeneric(PropertyMaker)
058: */
059: public void useGeneric(PropertyMaker generic) {
060: super .useGeneric(generic);
061: if (generic instanceof CompoundPropertyMaker) {
062: CompoundPropertyMaker compoundGeneric = (CompoundPropertyMaker) generic;
063: for (int i = 0; i < Constants.COMPOUND_COUNT; i++) {
064: PropertyMaker submaker = compoundGeneric.subproperties[i];
065: if (submaker != null) {
066: addSubpropMaker((PropertyMaker) submaker.clone());
067: }
068: }
069: }
070: }
071:
072: /**
073: * Add a subproperty to this maker.
074: * @param subproperty
075: */
076: public void addSubpropMaker(PropertyMaker subproperty) {
077: // Place the base propId in the propId of the subproperty.
078: subproperty.propId &= Constants.COMPOUND_MASK;
079: subproperty.propId |= propId;
080:
081: subproperties[getSubpropIndex(subproperty.getPropId())] = subproperty;
082:
083: // Store the first subproperty with a setByShorthand. That subproperty
084: // will be used for converting a value set on the base property.
085: if (shorthandMaker == null && subproperty.setByShorthand) {
086: shorthandMaker = subproperty;
087: }
088: }
089:
090: /**
091: * Return a Maker object which is used to set the values on components
092: * of compound property types, such as "space".
093: * Overridden by property maker subclasses which handle
094: * compound properties.
095: * @param subpropertyId the id of the component for which a Maker is to
096: * returned, for example CP_OPTIMUM, if the FO attribute is
097: * space.optimum='10pt'.
098: * @return the Maker object specified
099: */
100: public PropertyMaker getSubpropMaker(int subpropertyId) {
101: return subproperties[getSubpropIndex(subpropertyId)];
102: }
103:
104: /**
105: * Calculate the real value of a subproperty by unmasking and shifting
106: * the value into the range [0 - (COMPOUND_COUNT-1)].
107: * The value is used as index into the subproperties array.
108: * @param propId the property id of the sub property.
109: * @return the array index.
110: */
111: private int getSubpropIndex(int subpropertyId) {
112: return ((subpropertyId & Constants.COMPOUND_MASK) >> Constants.COMPOUND_SHIFT) - 1;
113: }
114:
115: /**
116: * For compound properties which can take enumerate values.
117: * Delegate the enumeration check to one of the subpropeties.
118: * @param value the string containing the property value
119: * @return the Property encapsulating the enumerated equivalent of the
120: * input value
121: */
122: protected Property checkEnumValues(String value) {
123: Property result = null;
124: if (shorthandMaker != null) {
125: result = shorthandMaker.checkEnumValues(value);
126: }
127: if (result == null) {
128: result = super .checkEnumValues(value);
129: }
130: return result;
131: }
132:
133: /**
134: * Return the property on the current FlowObject. Depending on the passed flags,
135: * this will try to compute it based on other properties, or if it is
136: * inheritable, to return the inherited value. If all else fails, it returns
137: * the default value.
138: * @param subpropertyId The subproperty id of the property being retrieved.
139: * Is 0 when retriving a base property.
140: * @param propertyList The PropertyList object being built for this FO.
141: * @param tryInherit true if inherited properties should be examined.
142: * @param tryDefault true if the default value should be returned.
143: */
144: public Property get(int subpropertyId, PropertyList propertyList,
145: boolean tryInherit, boolean tryDefault)
146: throws PropertyException {
147: Property p = super .get(subpropertyId, propertyList, tryInherit,
148: tryDefault);
149: if (subpropertyId != 0 && p != null) {
150: p = getSubprop(p, subpropertyId);
151: }
152: return p;
153: }
154:
155: /**
156: * Return a Property object based on the passed Property object.
157: * This method is called if the Property object built by the parser
158: * isn't the right type for this compound property.
159: * @param p The Property object return by the expression parser
160: * @param propertyList The PropertyList object being built for this FO.
161: * @param fo The parent FO for the FO whose property is being made.
162: * @return A Property of the correct type or null if the parsed value
163: * can't be converted to the correct type.
164: * @throws PropertyException for invalid or inconsistent FO input
165: */
166: protected Property convertProperty(Property p,
167: PropertyList propertyList, FObj fo)
168: throws PropertyException {
169: // Delegate to the subproperty maker to do conversions.
170: p = shorthandMaker.convertProperty(p, propertyList, fo);
171:
172: if (p != null) {
173: Property prop = makeCompound(propertyList, fo);
174: CompoundDatatype pval = (CompoundDatatype) prop.getObject();
175: for (int i = 0; i < Constants.COMPOUND_COUNT; i++) {
176: PropertyMaker submaker = subproperties[i];
177: if (submaker != null && submaker.setByShorthand) {
178: pval.setComponent(submaker.getPropId()
179: & Constants.COMPOUND_MASK, p, false);
180: }
181: }
182: return prop;
183: }
184: return null;
185: }
186:
187: /**
188: * Make a compound property with default values.
189: * @param propertyList The PropertyList object being built for this FO.
190: * @return the Property object corresponding to the parameters
191: * @throws PropertyException for invalid or inconsisten FO input
192: */
193: public Property make(PropertyList propertyList)
194: throws PropertyException {
195: if (defaultValue != null) {
196: return make(propertyList, defaultValue, propertyList
197: .getParentFObj());
198: } else {
199: return makeCompound(propertyList, propertyList
200: .getParentFObj());
201: }
202: }
203:
204: /**
205: * Create a Property object from an attribute specification.
206: * @param propertyList The PropertyList object being built for this FO.
207: * @param value The attribute value.
208: * @param fo The parent FO for the FO whose property is being made.
209: * @return The initialized Property object.
210: * @throws PropertyException for invalid or inconsistent FO input
211: */
212: public Property make(PropertyList propertyList, String value,
213: FObj fo) throws PropertyException {
214: Property p = super .make(propertyList, value, fo);
215: p = convertProperty(p, propertyList, fo);
216: return p;
217: }
218:
219: /**
220: * Return a property value for a compound property. If the property
221: * value is already partially initialized, this method will modify it.
222: * @param baseProperty The Property object representing the compound property,
223: * for example: SpaceProperty.
224: * @param subpropertyId The Constants ID of the subproperty (component)
225: * whose value is specified.
226: * @param propertyList The propertyList being built.
227: * @param fo The parent FO for the FO whose property is being made.
228: * @param value the value of the
229: * @return baseProperty (or if null, a new compound property object) with
230: * the new subproperty added
231: * @throws PropertyException for invalid or inconsistent FO input
232: */
233: public Property make(Property baseProperty, int subpropertyId,
234: PropertyList propertyList, String value, FObj fo)
235: throws PropertyException {
236: if (baseProperty == null) {
237: baseProperty = makeCompound(propertyList, fo);
238: }
239:
240: PropertyMaker spMaker = getSubpropMaker(subpropertyId);
241:
242: if (spMaker != null) {
243: Property p = spMaker.make(propertyList, value, fo);
244: if (p != null) {
245: return setSubprop(baseProperty, subpropertyId
246: & Constants.COMPOUND_MASK, p);
247: }
248: } else {
249: //getLogger().error("compound property component "
250: // + partName + " unknown.");
251: }
252: return baseProperty;
253: }
254:
255: /**
256: * Create a empty compound property and fill it with default values for
257: * the subproperties.
258: * @param propertyList The propertyList being built.
259: * @param parentFO The parent FO for the FO whose property is being made.
260: * @return a Property subclass object holding a "compound" property object
261: * initialized to the default values for each component.
262: * @throws PropertyException ...
263: */
264: protected Property makeCompound(PropertyList propertyList,
265: FObj parentFO) throws PropertyException {
266: Property p = makeNewProperty();
267: CompoundDatatype data = (CompoundDatatype) p.getObject();
268: for (int i = 0; i < Constants.COMPOUND_COUNT; i++) {
269: PropertyMaker subpropertyMaker = subproperties[i];
270: if (subpropertyMaker != null) {
271: Property subproperty = subpropertyMaker
272: .make(propertyList);
273: data.setComponent(subpropertyMaker.getPropId()
274: & Constants.COMPOUND_MASK, subproperty, true);
275: }
276: }
277: return p;
278: }
279: }
|