View Javadoc

1   /*
2    * Copyright 2004-2005, 2007 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package net.sf.morph.transform.transformers;
17  
18  import net.sf.composite.Defaults;
19  import net.sf.composite.SimpleComposite;
20  import net.sf.composite.StrictlyTypedComposite;
21  import net.sf.composite.validate.ComponentValidator;
22  import net.sf.morph.transform.NodeCopier;
23  import net.sf.morph.transform.Transformer;
24  import net.sf.morph.util.ClassUtils;
25  import net.sf.morph.util.ContainerUtils;
26  
27  /**
28   * @author Matt Sgarlata
29   * @since Dec 12, 2004
30   */
31  public abstract class BaseCompositeTransformer extends BaseTransformer implements Transformer, SimpleComposite, StrictlyTypedComposite {
32  
33  	/** Our component list */
34  	protected Object[] components;
35  	private ComponentValidator componentValidator;
36  
37  // internal state validation
38  
39  	// TODO consider doing validation when data is specified rather than waiting
40  	// until the user tries to perform an operation
41  
42  	/**
43  	 * {@inheritDoc}
44  	 * @see net.sf.morph.transform.transformers.BaseTransformer#initializeImpl()
45  	 */
46  	protected void initializeImpl() throws Exception {
47  		super.initializeImpl();
48  		getComponentValidator().validate(this);
49  		if (isNarrowingComponentArray()) {
50  			if (components != null
51  					&& !getComponentType().isAssignableFrom(
52  							components.getClass().getComponentType())) {
53  				Object[] newComponents = (Object[]) ClassUtils.createArray(
54  						getComponentType(), components.length);
55  				System.arraycopy(components, 0, newComponents, 0, components.length);
56  				components = newComponents;
57  			}
58  		}
59  		updateNestedTransformerComponents(getNestedTransformer(), null);
60  	}
61  
62  // information about the components of a composite transformer
63  
64  	/**
65  	 * Return the component type of this transformer.
66  	 * @return Class
67  	 */
68  	public Class getComponentType() {
69  		return Transformer.class;
70  	}
71  
72  	/**
73  	 * {@inheritDoc}
74  	 * @see net.sf.composite.SimpleComposite#getComponents()
75  	 */
76  	public Object[] getComponents() {
77  		return components;
78  	}
79  
80  	/**
81  	 * {@inheritDoc}
82  	 * @see net.sf.composite.SimpleComposite#setComponents(java.lang.Object[])
83  	 */
84  	public void setComponents(Object[] components) {
85  		setInitialized(false);
86  		this.components = components;
87  	}
88  
89  	/**
90  	 * Return the ComponentValidator of this transformer.
91  	 * @return ComponentValidator
92  	 */
93  	public ComponentValidator getComponentValidator() {
94  		if (componentValidator == null) {
95  			componentValidator = Defaults.createComponentValidator();
96  		}
97  		return componentValidator;
98  	}
99  
100 	/**
101 	 * Set the ComponentValidator for this transformer.
102 	 * @param componentValidator ComponentValidator
103 	 */
104 	public void setComponentValidator(ComponentValidator componentValidator) {
105 		this.componentValidator = componentValidator;
106 	}
107 
108 	/* (non-Javadoc)
109 	 * @see net.sf.morph.transform.transformers.BaseTransformer#setNestedTransformer(net.sf.morph.transform.Transformer)
110 	 */
111 	protected void setNestedTransformer(Transformer nestedTransformer) {
112 		Transformer old = getNestedTransformer();
113 		super.setNestedTransformer(nestedTransformer);
114 		updateNestedTransformerComponents(nestedTransformer, old);
115 	}
116 
117 	/**
118 	 * Propagate our nested transformer to any component NodeCopiers.
119 	 * @param incoming
120 	 * @param outgoing
121 	 */
122 	protected void updateNestedTransformerComponents(Transformer incoming, Transformer outgoing) {
123 		if (incoming == outgoing) {
124 			return;
125 		}
126 		NodeCopier[] nodeCopiers = (NodeCopier[]) ContainerUtils.getElementsOfType(getComponents(), NodeCopier.class);
127 		for (int i = 0; nodeCopiers != null && i < nodeCopiers.length; i++) {
128 			if (nodeCopiers[i].getNestedTransformer() == outgoing) {
129 				nodeCopiers[i].setNestedTransformer(incoming);
130 			}
131 		}
132 	}
133 
134 	/**
135 	 * {@inheritDoc}
136 	 * @see net.sf.morph.transform.transformers.BaseTransformer#isWrappingRuntimeExceptions()
137 	 */
138 	protected boolean isWrappingRuntimeExceptions() {
139 		// composite transformers will often have user specified components,
140 		// in which case we want to allow user user defined RuntimeExceptions
141 		// to propogate up the stack.  Morph transformers will already throw
142 		// TransformationExceptions so if all the composites are transformers
143 		// that come with Morph, TransformationExceptions will get thrown
144 	    return false;
145     }
146 
147 	/**
148 	 * Learn whether we should automatically narrow the array type of <code>components</code>
149 	 * to that returned by {@link #getComponentType()} after validating the components.
150 	 * @return default <code>true</code>
151 	 */
152 	protected boolean isNarrowingComponentArray() {
153 		return true;
154 	}
155 }