001: //$Id: BeanCreatorAction.java 250 2006-08-25 21:30:26Z jg_hamburg $
002: /********************************************************************************
003: * DDTUnit, a Datadriven Approach to Unit- and Moduletesting
004: * Copyright (c) 2004, Joerg and Kai Gellien
005: * All rights reserved.
006: *
007: * The Software is provided under the terms of the Common Public License 1.0
008: * as provided with the distribution of DDTUnit in the file cpl-v10.html.
009: * Redistribution and use in source and binary forms, with or without
010: * modification, are permitted provided that the following conditions
011: * are met:
012: *
013: * + Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * + Redistributions in binary form must reproduce the above
017: * copyright notice, this list of conditions and the following
018: * disclaimer in the documentation and/or other materials provided
019: * with the distribution.
020: *
021: * + Neither the id of the authors or DDTUnit, nor the
022: * names of its contributors may be used to endorse or promote
023: * products derived from this software without specific prior
024: * written permission.
025: *
026: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
027: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
028: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
029: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
030: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
031: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
032: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
033: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
036: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: ********************************************************************************/package junitx.ddtunit.data.processing;
038:
039: import java.lang.reflect.Method;
040: import java.util.Collection;
041: import java.util.HashMap;
042: import java.util.List;
043: import java.util.Map;
044: import java.util.Vector;
045:
046: import junitx.ddtunit.DDTException;
047: import junitx.ddtunit.data.DDTTestDataException;
048: import junitx.ddtunit.data.TypedObject;
049: import junitx.ddtunit.util.ClassAnalyser;
050:
051: /**
052: * This class contains object state and other information to create object from
053: * SAX event stream.
054: *
055: * @author jg
056: */
057: public class BeanCreatorAction extends ActionBase {
058: /**
059: *
060: * Constructor used as standard constructor to instanciate actions of this
061: * type
062: *
063: * @param attrMap
064: */
065: public BeanCreatorAction(Map attrMap) {
066: super (attrMap);
067: }
068:
069: /*
070: * (non-Javadoc)
071: *
072: * @see junitx.ddtunit.parser.ActionBase#process()
073: */
074: public IAction process() {
075: log.debug("process BeanCreator - START");
076: IAction rootAction = this .getPrevious();
077: if (!this .successorProcessed) {
078: processNoSuccessor();
079: }
080: if (rootAction != null) {
081: String hintValue = rootAction.getHint();
082:
083: if (HintTypes.COLLECTION.equals(hintValue)) {
084: rootAction.processSuccessor(this );
085: } else if (HintTypes.MAP.equals(hintValue)) {
086: rootAction.processSuccessor(this );
087: } else if (HintTypes.ATTRLIST.equals(hintValue)) {
088: rootAction.processSuccessor(this );
089: } else if (HintTypes.FIELDS.equals(hintValue)) {
090: rootAction.processSuccessor(this );
091: } else if (HintTypes.CONSTRUCTOR.equals(hintValue)
092: || HintTypes.CALL.equals(hintValue)) {
093: rootAction.processSuccessor(this );
094: } else if (HintTypes.BEAN.equals(hintValue)) {
095: rootAction.processSuccessor(this );
096: } else if (HintTypes.ARRAY.equals(hintValue)) {
097: rootAction.processSuccessor(this );
098: } else if (HintTypes.INTERNAL_MAPENTRY.equals(hintValue)) {
099: rootAction.processSuccessor(this );
100: } else {
101: throw new DDTException("Unknown hint (" + hintValue
102: + ")- stop processing.");
103: }
104: }
105: this .pop();
106: return this ;
107: }
108:
109: /**
110: * If no content on tag is provided just instanciate object by default
111: * constructor.
112: */
113: public void processNoSuccessor() {
114: // process direct object call providing no parameters (empty tag)
115: IAction action = new AttributeListCreatorAction(new HashMap());
116: action.inject();
117: action.setValue(new Vector());
118: this .insert(action);
119: action.process();
120: }
121:
122: /*
123: * (non-Javadoc)
124: *
125: * @see junitx.ddtunit.parser.ActionBase#inject()
126: */
127: public IAction inject() {
128: String type = (String) this .attrMap
129: .get(ParserConstants.XML_ATTR_TYPE);
130: String id = (String) this .attrMap
131: .get(ParserConstants.XML_ATTR_ID);
132: this .injectedObject = new TypedObject(id, type);
133: return this ;
134: }
135:
136: public void processSuccessor(IAction successor) {
137: log.debug("processSuccessor(" + successor + ") - START");
138: // create attribute list action and insert after rootAction
139: if (HintTypes.ATTRLIST.equals(successor.getHint())) {
140: List fields = (List) successor.getObject().getValue();
141: TypedObject field = null;
142: StringBuffer setter = new StringBuffer();
143: try {
144: // returned type is never used but method may specify this type
145: // internally in injected object
146: this .getType();
147: if (this .getValue() == null) {
148: this .createObject();
149: }
150: for (int count = 0; count < fields.size(); count++) {
151: field = (TypedObject) fields.get(count);
152: // check for existing setter
153: setter.replace(0, setter.length(), "set");
154: setter
155: .append(
156: field.getId().substring(0, 1)
157: .toUpperCase()).append(
158: field.getId().substring(1));
159: Class fieldClazz = field.getValue().getClass();
160: Class[] args = new Class[1];
161: args[0] = fieldClazz;
162: Method setMethod = (Method) ClassAnalyser
163: .findMethodByParams(this .getType(), setter
164: .toString(), args);
165: setMethod.setAccessible(true);
166: Object[] objs = new Object[1];
167: objs[0] = field.getValue();
168: setMethod.invoke(this .getValue(), objs);
169: }
170: } catch (Exception ex) {
171: StringBuffer sb = new StringBuffer(
172: "Error executing setter ")
173: .append(this .getType())
174: .append(".")
175: .append(setter)
176: .append("(...). ")
177: .append(
178: "Check if hint and setter are correct (Do not provide set-prefix!).");
179: throw new DDTException(sb.toString(), ex);
180: }
181: } else if (HintTypes.COLLECTION.equals(successor.getHint())) {
182: // provide a Collection as setter argument
183: Collection param = (Collection) successor.getObject()
184: .getValue();
185: TypedObject field = successor.getObject();
186: StringBuffer setter = new StringBuffer();
187: try {
188: // returned type is never used but method may specify this type
189: // internally in injected object
190: this .getType();
191: if (this .getValue() == null) {
192: this .createObject();
193: }
194: // check for existing setter
195: setter.replace(0, setter.length(), "set");
196: setter.append(
197: field.getId().substring(0, 1).toUpperCase())
198: .append(field.getId().substring(1));
199: Class fieldClazz = field.getValue().getClass();
200: Class[] args = new Class[1];
201: args[0] = fieldClazz;
202: Method setMethod = (Method) ClassAnalyser
203: .findMethodByParams(this .getType(), setter
204: .toString(), args);
205: setMethod.setAccessible(true);
206: Object[] objs = new Object[1];
207: objs[0] = field.getValue();
208: setMethod.invoke(this .getValue(), objs);
209: } catch (Exception ex) {
210: StringBuffer sb = new StringBuffer(
211: "Error executing setter ")
212: .append(this .getType())
213: .append(".")
214: .append(setter)
215: .append("(...). ")
216: .append(
217: "Check if hint and setter are correct (Do not provide set-prefix!).");
218: throw new DDTException(sb.toString(), ex);
219: }
220: } else if (HintTypes.CONTENT.equals(successor.getHint())) {
221: if (!ContentCreatorAction.CONTENT_NULL.equals(successor
222: .getValue().toString())) {
223: throw new DDTTestDataException(
224: "Unsupported content for BeanCreator:"
225: + successor.getValue().toString());
226: }
227: } else {
228: // ARRAY successor
229: Map attribMap = new HashMap();
230: IAction attribListAction = ActionFactory.getAction(
231: ActionState.ATTRLIST_CREATION, attribMap);
232: this .insert(attribListAction);
233: try {
234: // create container
235: attribListAction.createObject();
236: // initialize with first list element
237: ((List) attribListAction.getValue()).add(successor
238: .getObject());
239: } catch (Exception ex) {
240: throw new DDTException("Error on action processing", ex);
241: }
242: }
243: this .successorProcessed = true;
244: }
245:
246: }
|