1 package com.sri.emo.wizard.selection.management;
2
3 import com.jcorporate.expresso.core.controller.ControllerException;
4 import com.jcorporate.expresso.core.controller.ErrorCollection;
5 import com.jcorporate.expresso.core.controller.ExpressoRequest;
6 import com.jcorporate.expresso.core.db.DBException;
7 import com.jcorporate.expresso.core.db.exception.DBRecordNotFoundException;
8 import com.jcorporate.expresso.services.controller.ui.DefaultAutoElement;
9 import com.sri.emo.dbobj.*;
10 import org.apache.log4j.Logger;
11
12 import java.util.HashMap;
13 import java.util.Map;
14
15 /***
16 * This object takes a a set of strings equaling parameters and constructs
17 * and validates a wizard step object based on those parameters.
18 *
19 * @author Michael Rimov
20 */
21 public class StepParameterParser {
22
23 /***
24 * Used for logging errors.
25 */
26 private static final Logger log = Logger.getLogger(StepParameterParser.class);
27
28 /***
29 * A set of parameters keyed by string pointing to strings.
30 */
31 private final ExpressoRequest request;
32
33 /***
34 * Constructor that takes a map of parameters usually as defined by the
35 * Expresso's <tt>ExpressoRequest</tt> object.
36 *
37 * @param controllerRequest ExpressoRequest
38 * @todo refactor this to use a parameter map instead.
39 */
40 public StepParameterParser(final ExpressoRequest controllerRequest) {
41 this.request = controllerRequest;
42 }
43
44 /***
45 * Similar to parseStep, but it validates as well. Useful for once
46 * workflow is complete and you need to save to database.
47 *
48 * @param ec ErrorCollection [in/out] The error collection is populated with any errors
49 * that occur while parsing the steps.
50 * @return WizStep the constructed wizard step.
51 * @throws DBException upon error constructing or setting fields of the wizard step.
52 */
53 public WizStep parseAndValidate(ErrorCollection ec) throws DBException {
54
55 WizStep ws = null;
56
57
58 try {
59 ws = (WizStep) DefaultAutoElement.getAutoControllerElement().
60 parseDBObject(request, constructWizStep(), ec,
61 true);
62 } catch (ControllerException ex) {
63 throw new DBException("Error parsing DBObject");
64 }
65
66
67
68 ws.setStepAttributes(filterAndValidateStepAttributes(request.getAllParameters(), ec));
69
70
71 return ws;
72 }
73
74 /***
75 * Returns a wizard step instance based on the parameters set in the constructor.
76 *
77 * @param ec ErrorCollection [in/out] The error collection is populated with any errors
78 * that occur while parsing the steps.
79 * @return WizStep the constructed wizard step.
80 * @throws DBException upon error constructing or setting fields of the wizard step.
81 */
82 public WizStep parseStep(ErrorCollection ec) throws DBException {
83
84
85 WizStep ws;
86
87
88 try {
89 ws = (WizStep) DefaultAutoElement.getAutoControllerElement().parseDBObject(request, constructWizStep(), ec,
90 false);
91 } catch (ControllerException ex) {
92 throw new DBException("Error parsing DBObject");
93 }
94
95
96
97 Map attributes = filterAndValidateStepAttributes(request.getAllParameters(), ec);
98 if (attributes.size() > 0) {
99 /*** @todo We may need to set it one by one if we're having consistancy problems */
100 ws.setStepAttributes(attributes);
101 }
102
103
104 return ws;
105 }
106
107 private WizStep constructWizStep() throws DBException {
108 WizStep ws = new WizStep();
109 String id = request.getParameter(WizStep.FLD_ID);
110 if (id != null && id.length() > 0) {
111 ws.setId(id);
112 ws.retrieve();
113 }
114
115 return ws;
116 }
117
118 /***
119 * Parses the appropriate attributes from the request parameters and validates them
120 * for bad input.
121 *
122 * @param allParameters All parameters to sort out.
123 * @param ec the error collection to fill out any specific errors associated
124 * with invalidparameters.
125 * @return Map a map of attributes keyed by strings, pointing to strings.
126 */
127 private static Map filterAndValidateStepAttributes(final Map allParameters, ErrorCollection ec) {
128 Map filteredParameters = null;
129 try {
130 filteredParameters = new HashMap();
131 String val;
132
133
134 val = (String) allParameters.get(StepAttributes.ATTRIBUTE_INSTANCE_ID);
135 if (val != null && val.length() > 0) {
136 try {
137
138
139 Node node = new Node();
140 node.setField(Node.NODE_ID, val);
141 node.retrieve();
142
143
144
145 NodeType nt = new NodeType();
146 nt.setEntityName(node.getNodeType());
147
148 if (!nt.find()) {
149 ec.addError("Could not find node type of: " + node.getNodeType());
150 } else {
151
152
153
154 Part[] allParts = nt.getParts();
155 if (allParts.length == 0) {
156 ec.addError("No parts defined for this node type.");
157 } else {
158 boolean validated = false;
159 for (int i = 0; i < allParts.length; i++) {
160 if (allParts[i].getCardinality().equals(Part.MULTIPLE_ALLOWED)) {
161 validated = true;
162 break;
163 }
164 }
165
166 if (!validated) {
167 ec.addError("We were unable to locate any parts in the model that allowed"
168 + " multiple attributes. Please check the model documentation");
169 } else {
170 filteredParameters.put(StepAttributes.ATTRIBUTE_INSTANCE_ID, val);
171 }
172 }
173 }
174 } catch (DBRecordNotFoundException ex) {
175 ec.addError("Could not find node of id: " + val);
176 }
177 }
178
179
180 val = (String) allParameters.get(StepAttributes.ATTRIBUTE_INSTANCE_FIELD);
181 if (val != null && val.length() > 0) {
182
183 if (filteredParameters.containsKey(StepAttributes.ATTRIBUTE_INSTANCE_ID)) {
184 try {
185 PartsFactory.getPart(val);
186 Part part = new Part();
187 part.setId(val);
188 part.retrieve();
189 } catch (DBRecordNotFoundException ex2) {
190 ec.addError("Could not find part of node with id: " + val);
191 }
192 filteredParameters.put(StepAttributes.ATTRIBUTE_INSTANCE_FIELD, val);
193 } else {
194 ec.addError("A node ID must be defined before an attribute ID can be set.");
195 }
196 }
197
198
199 val = (String) allParameters.get(StepAttributes.ATTRIBUTE_MODEL);
200 if (val != null && val.length() > 0) {
201
202 NodeType nt = new NodeType();
203 nt.setField(NodeType.NODE_TYPE_ID, val);
204
205 if (!nt.find()) {
206 ec.addError("Could not find node type of: " + val);
207 } else {
208 filteredParameters.put(StepAttributes.ATTRIBUTE_MODEL, val);
209 }
210
211 }
212
213
214 val = (String) allParameters.get(StepAttributes.ATTRIBUTE_MODEL_FIELD);
215 if (val != null && val.length() > 0) {
216 if (filteredParameters.containsKey(StepAttributes.ATTRIBUTE_MODEL)) {
217
218 try {
219 NodeType nt = new NodeType();
220 nt.setId((String) filteredParameters.get(StepAttributes.ATTRIBUTE_MODEL));
221 nt.retrieve();
222 Part[] parts = nt.getParts();
223 Part foundPart = null;
224 for (int i = 0; i < parts.length; i++) {
225 if (parts[i].getId().equals(val)) {
226 foundPart = parts[i];
227 }
228 }
229
230
231 if (foundPart == null) {
232 ec.addError("Could not find the part of the model with ID:" + val);
233 } else {
234 filteredParameters.put(StepAttributes.ATTRIBUTE_MODEL_FIELD, val);
235
236 }
237 } catch (DBRecordNotFoundException ex1) {
238 ec.addError("Could not find the part of the model with ID:" + val);
239 }
240 } else {
241 ec.addError("A Model Id must be defined before a field can be chosen");
242 }
243 }
244
245
246 val = (String) allParameters.get(StepAttributes.ATTRIBUTE_TEXT_STYLE);
247 if (val != null && val.length() > 0) {
248 if (StepAttributes.TEXT_VV_MULTILINE.equals(val) || StepAttributes.TEXT_VV_SINGLELINE.equals(val)) {
249 filteredParameters.put(StepAttributes.ATTRIBUTE_TEXT_STYLE, val);
250 } else {
251 ec.addError("Invalid text style: " + val);
252 }
253 }
254
255
256 val = (String) allParameters.get(StepAttributes.ATTRIBUTE_PICKLIST_ID);
257 if (val != null && val.length() > 0) {
258 PickList pick = new PickList();
259 pick.setPickAttribType(val);
260 if (pick.find()) {
261 filteredParameters.put(StepAttributes.ATTRIBUTE_PICKLIST_ID, val);
262 } else {
263 ec.addError("Invalid picklist attribute: " + val);
264 }
265 }
266
267 } catch (Throwable ex) {
268 log.error("Error parsing step attributes: " + ex.getMessage(), ex);
269 ec.addError("There was a error parsing step attributes:" + ex.getMessage());
270 }
271
272 return filteredParameters;
273 }
274 }