View Javadoc

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          //construct a new wizard step
55          WizStep ws = null;
56  
57          //fill in fields of the wizard step and validate
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          //retrieve all appropriate parameters that are attributes of the step.
67          //set the attributes
68          ws.setStepAttributes(filterAndValidateStepAttributes(request.getAllParameters(), ec));
69  
70          //return the fully constructed wizard step
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          //construct a new wizard step
85          WizStep ws;
86  
87          //fill in fields of the wizard step.
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          //retrieve all appropriate parameters that are attributes of the step.
96          //set the attributes
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         //return the fully constructed wizard step
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             //Parse Node Ids
134             val = (String) allParameters.get(StepAttributes.ATTRIBUTE_INSTANCE_ID);
135             if (val != null && val.length() > 0) {
136                 try {
137 
138                     //Validate Node Ids
139                     Node node = new Node();
140                     node.setField(Node.NODE_ID, val);
141                     node.retrieve();
142 
143                     //Ok, we found the node.  Now check that it has any parts
144                     //that can be used for multiple attributes
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                         //Check the parts to make sure that at least one
153                         //part is available that has cardinality of MULTIPLE_ALLOWED
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             //parse attribute instance fields
180             val = (String) allParameters.get(StepAttributes.ATTRIBUTE_INSTANCE_FIELD);
181             if (val != null && val.length() > 0) {
182                 //check to make sure a node ID has been set because it is required for an instance attribute
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             //Parse the model id.
199             val = (String) allParameters.get(StepAttributes.ATTRIBUTE_MODEL);
200             if (val != null && val.length() > 0) {
201                 //Check the model id.
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             //Parse the model field.
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                         //If we did not find a part
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             // parse text style
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             // parse picklist
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 }