Clover Coverage Report - KS Common Impl 1.2-M3-SNAPSHOT
Coverage timestamp: Mon Jun 6 2011 05:48:16 EDT
../../../../../../img/srcFileCovDistChart7.png 20% of files have more coverage
291   676   125   11.19
140   464   0.43   13
26     4.81  
2    
 
  MetadataServiceImpl       Line # 48 280 0% 121 140 68.2% 0.6818182
  MetadataServiceImpl.RecursionCounter       Line # 55 11 0% 4 3 82.4% 0.8235294
 
  (4)
 
1    /**
2    * Copyright 2010 The Kuali Foundation Licensed under the Educational Community License, Version 2.0 (the "License"); you may
3    * not use this file except in compliance with the License. You may obtain a copy of the License at
4    * http://www.osedu.org/licenses/ECL-2.0 Unless required by applicable law or agreed to in writing, software distributed
5    * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
6    * implied. See the License for the specific language governing permissions and limitations under the License.
7    */
8   
9    package org.kuali.student.common.assembly.dictionary;
10   
11    import java.text.DateFormat;
12    import java.text.ParseException;
13    import java.text.SimpleDateFormat;
14    import java.util.ArrayList;
15    import java.util.HashMap;
16    import java.util.List;
17    import java.util.Map;
18   
19    import org.apache.log4j.Logger;
20    import org.kuali.student.common.assembly.data.ConstraintMetadata;
21    import org.kuali.student.common.assembly.data.Data;
22    import org.kuali.student.common.assembly.data.LookupMetadata;
23    import org.kuali.student.common.assembly.data.LookupParamMetadata;
24    import org.kuali.student.common.assembly.data.Metadata;
25    import org.kuali.student.common.assembly.data.UILookupConfig;
26    import org.kuali.student.common.assembly.data.UILookupData;
27    import org.kuali.student.common.assembly.data.Data.DataType;
28    import org.kuali.student.common.assembly.data.Data.Value;
29    import org.kuali.student.common.assembly.data.Metadata.WriteAccess;
30    import org.kuali.student.common.dictionary.dto.CaseConstraint;
31    import org.kuali.student.common.dictionary.dto.CommonLookupParam;
32    import org.kuali.student.common.dictionary.dto.Constraint;
33    import org.kuali.student.common.dictionary.dto.FieldDefinition;
34    import org.kuali.student.common.dictionary.dto.ObjectStructureDefinition;
35    import org.kuali.student.common.dictionary.dto.WhenConstraint;
36    import org.kuali.student.common.dictionary.service.DictionaryService;
37    import org.kuali.student.common.dto.DtoConstants.DtoState;
38    import org.kuali.student.common.validation.dto.ValidationResultInfo.ErrorLevel;
39    import org.springframework.beans.BeanUtils;
40    import org.springframework.context.ApplicationContext;
41    import org.springframework.context.support.ClassPathXmlApplicationContext;
42   
43    /**
44    * This class provides metadata lookup for service dto objects.
45    *
46    * @author Kuali Student Team
47    */
 
48    public class MetadataServiceImpl {
49    final Logger LOG = Logger.getLogger(MetadataServiceImpl.class);
50   
51    private Map<String, DictionaryService> dictionaryServiceMap;
52    private List<UILookupConfig> lookupObjectStructures;
53    private String uiLookupContext;
54   
 
55    private static class RecursionCounter {
56    public static final int MAX_DEPTH = 4;
57   
58    private Map<String, Integer> recursions = new HashMap<String, Integer>();
59   
 
60  15 toggle public int increment(String objectName) {
61  15 Integer hits = recursions.get(objectName);
62   
63  15 if (hits == null) {
64  15 hits = new Integer(1);
65    } else {
66  0 hits++;
67    }
68  15 recursions.put(objectName, hits);
69  15 return hits;
70    }
71   
 
72  15 toggle public int decrement(String objectName) {
73  15 Integer hits = recursions.get(objectName);
74  15 if (hits >= 1) {
75  15 hits--;
76    }
77   
78  15 recursions.put(objectName, hits);
79  15 return hits;
80    }
81    }
82   
83    /**
84    * Create a metadata service initializing it with all known dictionary services
85    *
86    * @param dictionaryServices
87    */
 
88  4 toggle public MetadataServiceImpl(DictionaryService... dictionaryServices) {
89  4 if (dictionaryServices != null) {
90  4 this.dictionaryServiceMap = new HashMap<String, DictionaryService>();
91  4 for (DictionaryService d : dictionaryServices) {
92  4 List<String> objectTypes = d.getObjectTypes();
93  4 for (String objectType : objectTypes) {
94  12 dictionaryServiceMap.put(objectType, d);
95    }
96    }
97    }
98    }
99   
100    /**
101    * This method gets the metadata for the given object key, type, state and nextState
102    *
103    * @param objectKey
104    * @param type The type of the object (value can be null)
105    * @param state The state for which to retrieve object constraints (value can be null)
106    * @param nextState The state to to check requiredForNextState indicators (value can be null)
107    * @return
108    */
 
109  15 toggle public Metadata getMetadata(String objectKey, String type, String state, String nextState) {
110  15 return getMetadataFromDictionaryService(objectKey, type, state, nextState);
111    }
112   
113    /**
114    * This method gets the metadata for the given object key, type and state
115    *
116    * @param objectKey
117    * @param type The type of the object (value can be null)
118    * @param state The state for which to retrieve object constraints (value can be null)
119    * @return
120    */
 
121  15 toggle public Metadata getMetadata(String objectKey, String type, String state) {
122  15 return getMetadata(objectKey, type, state, null);
123    }
124   
125   
126    /**
127    * This method gets the metadata for the given object key and state
128    *
129    * @param objectKey
130    * @param type The type of the object (value can be null)
131    */
 
132  1 toggle public Metadata getMetadata(String objectKey, String state) {
133  1 return getMetadata(objectKey, null, state);
134    }
135   
136    /**
137    * This method gets the metadata for the given object key for state DRAFT.
138    *
139    * @see MetadataServiceImpl#getMetadata(String, String)
140    * @param objectKey
141    * @return
142    */
 
143  9 toggle public Metadata getMetadata(String objectKey) {
144  9 return getMetadata(objectKey, null, null);
145    }
146   
147    /**
148    * This invokes the appropriate dictionary service to get the object structure and then converts it to a metadata
149    * structure.
150    *
151    * @param objectKey
152    * @param type
153    * @param state
154    * @return
155    */
 
156  15 toggle protected Metadata getMetadataFromDictionaryService(String objectKey, String type, String state, String nextState) {
157  15 Metadata metadata = new Metadata();
158   
159  15 ObjectStructureDefinition objectStructure = getObjectStructure(objectKey);
160   
161  15 metadata.setProperties(getProperties(objectStructure, type, state, nextState, new RecursionCounter()));
162   
163  15 metadata.setWriteAccess(WriteAccess.ALWAYS);
164  15 metadata.setDataType(DataType.DATA);
165  15 addLookupstoMetadata(objectKey, metadata, type);
166  15 return metadata;
167    }
168   
169    /**
170    * This method is used to convert a list of dictionary fields into metadata properties
171    *
172    * @param fields
173    * @param type
174    * @param state
175    * @return
176    */
 
177  15 toggle private Map<String, Metadata> getProperties(ObjectStructureDefinition objectStructure, String type, String state, String nextState, RecursionCounter counter) {
178  15 String objectId = objectStructure.getName();
179  15 int hits = counter.increment(objectId);
180   
181  15 Map<String, Metadata> properties = null;
182   
183  15 if (hits < RecursionCounter.MAX_DEPTH) {
184  15 properties = new HashMap<String, Metadata>();
185   
186  15 List<FieldDefinition> attributes = objectStructure.getAttributes();
187  15 for (FieldDefinition fd : attributes) {
188   
189  81 Metadata metadata = new Metadata();
190   
191    // Set constraints, authz flags, default value
192  81 metadata.setWriteAccess(WriteAccess.ALWAYS);
193  81 metadata.setDataType(convertDictionaryDataType(fd.getDataType()));
194  81 metadata.setConstraints(getConstraints(fd, type, state, nextState));
195  81 metadata.setCanEdit(!fd.isReadOnly());
196  81 metadata.setCanUnmask(!fd.isMask());
197  81 metadata.setCanView(!fd.isHide());
198  81 metadata.setDynamic(fd.isDynamic());
199  81 metadata.setLabelKey(fd.getLabelKey());
200  81 metadata.setDefaultValue(convertDefaultValue(metadata.getDataType(), fd.getDefaultValue()));
201  81 metadata.setDefaultValuePath(fd.getDefaultValuePath());
202   
203  81 if (fd.isPartialMask()){
204  8 metadata.setPartialMaskFormatter(fd.getPartialMaskFormatter());
205    }
206   
207  81 if (fd.isMask()){
208  8 metadata.setMaskFormatter(fd.getMaskFormatter());
209    }
210   
211    // Get properties for nested object structure
212  81 Map<String, Metadata> nestedProperties = null;
213  81 if (fd.getDataType() == org.kuali.student.common.dictionary.dto.DataType.COMPLEX && fd.getDataObjectStructure() != null) {
214  0 nestedProperties = getProperties(fd.getDataObjectStructure(), type, state, nextState, counter);
215    }
216   
217    // For repeating field, create a LIST with wildcard in metadata structure
218  81 if (isRepeating(fd)) {
219  0 Metadata repeatingMetadata = new Metadata();
220  0 metadata.setDataType(DataType.LIST);
221   
222  0 repeatingMetadata.setWriteAccess(WriteAccess.ALWAYS);
223  0 repeatingMetadata.setOnChangeRefreshMetadata(false);
224  0 repeatingMetadata.setDataType(convertDictionaryDataType(fd.getDataType()));
225   
226  0 if (nestedProperties != null) {
227  0 repeatingMetadata.setProperties(nestedProperties);
228    }
229   
230  0 Map<String, Metadata> repeatingProperty = new HashMap<String, Metadata>();
231  0 repeatingProperty.put("*", repeatingMetadata);
232  0 metadata.setProperties(repeatingProperty);
233  81 } else if (nestedProperties != null) {
234  0 metadata.setProperties(nestedProperties);
235    }
236   
237  81 properties.put(fd.getName(), metadata);
238   
239    }
240    }
241   
242  15 counter.decrement(objectId);
243  15 return properties;
244    }
245   
246    /**
247    * This method determines if a field is repeating
248    *
249    * @param fd
250    * @return
251    */
 
252  81 toggle protected boolean isRepeating(FieldDefinition fd) {
253  81 boolean isRepeating = false;
254  81 try {
255  81 int maxOccurs = Integer.parseInt(fd.getMaxOccurs());
256  28 isRepeating = maxOccurs > 1;
257    } catch (NumberFormatException nfe) {
258  53 isRepeating = FieldDefinition.UNBOUNDED.equals(fd.getMaxOccurs());
259    }
260   
261  81 return isRepeating;
262    }
263   
264    /**
265    * This method gets the object structure for given objectKey from a dictionaryService
266    *
267    * @param objectKey
268    * @return
269    */
 
270  15 toggle protected ObjectStructureDefinition getObjectStructure(String objectKey) {
271  15 DictionaryService dictionaryService = dictionaryServiceMap.get(objectKey);
272   
273  15 if (dictionaryService == null) {
274  0 throw new RuntimeException("Dictionary service not provided for objectKey=[" + objectKey + "].");
275    }
276   
277  15 return dictionaryService.getObjectStructure(objectKey);
278    }
279   
 
280  81 toggle protected List<ConstraintMetadata> getConstraints(FieldDefinition fd, String type, String state, String nextState) {
281  81 List<ConstraintMetadata> constraints = new ArrayList<ConstraintMetadata>();
282   
283  81 ConstraintMetadata constraintMetadata = new ConstraintMetadata();
284   
285  81 updateConstraintMetadata(constraintMetadata, (Constraint) fd, type, state, nextState);
286  81 constraints.add(constraintMetadata);
287   
288  81 return constraints;
289    }
290   
291    /**
292    * This updates the constraintMetadata with defintions from the dictionary constraint field.
293    *
294    * @param constraintMetadata
295    * @param constraint
296    */
 
297  82 toggle protected void updateConstraintMetadata(ConstraintMetadata constraintMetadata, Constraint constraint, String type, String state, String nextState) {
298    // For now ignoring the serverSide flag and making determination of which constraints
299    // should be passed up to the UI via metadata.
300   
301    // Min Length
302  82 if (constraint.getMinLength() != null) {
303  57 constraintMetadata.setMinLength(constraint.getMinLength());
304    }
305   
306    // Max Length
307  82 try {
308  82 if (constraint.getMaxLength() != null) {
309  57 constraintMetadata.setMaxLength(Integer.parseInt(constraint.getMaxLength()));
310    }
311    // Do we need to add another constraint and label it required if minOccurs = 1
312    } catch (NumberFormatException nfe) {
313    // Ignoring an unbounded length, cannot be handled in metadata structure, maybe change Metadata to string or set
314    // to -1
315  0 constraintMetadata.setMaxLength(9999);
316    }
317   
318    // Min Occurs
319  82 if (constraint.getMinOccurs() != null) {
320  66 constraintMetadata.setMinOccurs(constraint.getMinOccurs());
321    }
322   
323    // Max Occurs
324  82 String maxOccurs = constraint.getMaxOccurs();
325  82 if (maxOccurs != null) {
326  28 try {
327  28 constraintMetadata.setMaxOccurs(Integer.parseInt(maxOccurs));
328  28 if (!FieldDefinition.SINGLE.equals(maxOccurs)) {
329  0 constraintMetadata.setId("repeating");
330    }
331    } catch (NumberFormatException nfe) {
332    // Setting unbounded to a value of 9999, since unbounded not handled by metadata
333  0 if (FieldDefinition.UNBOUNDED.equals(maxOccurs)) {
334  0 constraintMetadata.setId("repeating");
335  0 constraintMetadata.setMaxOccurs(9999);
336    }
337    }
338    }
339   
340    // Min Value
341  82 if (constraint.getExclusiveMin() != null) {
342  16 constraintMetadata.setMinValue(constraint.getExclusiveMin());
343    }
344   
345    // Max Value
346  82 if (constraint.getInclusiveMax() != null) {
347  8 constraintMetadata.setMaxValue(constraint.getInclusiveMax());
348    }
349   
350  82 if (constraint.getValidChars() != null) {
351  22 constraintMetadata.setValidChars(constraint.getValidChars().getValue());
352  22 constraintMetadata.setValidCharsMessageId(constraint.getValidChars().getLabelKey());
353    }
354   
355    // Case constraints
356  82 if (constraint.getCaseConstraint() != null) {
357  22 processCaseConstraint(constraintMetadata, constraint.getCaseConstraint(), type, state, nextState);
358    }
359    }
360   
 
361  22 toggle protected void processCaseConstraint(ConstraintMetadata constraintMetadata, CaseConstraint caseConstraint, String type, String state, String nextState) {
362  22 String fieldPath = caseConstraint.getFieldPath();
363  22 List<WhenConstraint> whenConstraints = caseConstraint.getWhenConstraint();
364   
365  22 fieldPath = (fieldPath != null ? fieldPath.toUpperCase() : fieldPath);
366  22 if ("STATE".equals(fieldPath)) {
367    // Process a state constraint
368   
369    // Defaults for state and nextState
370  8 state = (state == null ? DtoState.DRAFT.toString():state);
371  8 nextState = (nextState == null || nextState.length() <=0 ? DtoState.getNextStateAsString(state):nextState);
372   
373  8 if ("EQUALS".equals(caseConstraint.getOperator()) && whenConstraints != null) {
374  8 for (WhenConstraint whenConstraint : whenConstraints) {
375  8 List<Object> values = whenConstraint.getValues();
376  8 if (values != null) {
377  8 Constraint constraint = whenConstraint.getConstraint();
378   
379  8 if (constraint.getErrorLevel() == ErrorLevel.ERROR){
380    // Set the required for next state flag
381  8 if (values.contains(nextState)) {
382  7 if (constraint.getMinOccurs() != null && constraint.getMinOccurs() > 0) {
383  7 constraintMetadata.setRequiredForNextState(true);
384  7 constraintMetadata.setNextState(nextState);
385    }
386    }
387   
388    // Update constraints based on state constraints
389  8 if (values.contains(state.toUpperCase())) {
390  1 updateConstraintMetadata(constraintMetadata, constraint, type, state, nextState);
391    }
392    }
393    }
394    }
395    }
396  14 } else if ("TYPE".equals(fieldPath)) {
397    // Process a type constraint
398   
399  0 if ("EQUALS".equals(caseConstraint.getOperator()) && whenConstraints != null) {
400  0 for (WhenConstraint whenConstraint : whenConstraints) {
401  0 List<Object> values = whenConstraint.getValues();
402  0 if (values != null && values.contains(type)) {
403  0 Constraint constraint = whenConstraint.getConstraint();
404  0 updateConstraintMetadata(constraintMetadata, constraint, type, state, nextState);
405    }
406    }
407    }
408    }
409    }
410   
411    /**
412    * Convert Object value to respective DataType. Method return null for object Value.
413    *
414    * @param dataType
415    * @param value
416    * @return
417    */
 
418  81 toggle protected Value convertDefaultValue(DataType dataType, Object value) {
419  81 Value v = null;
420  81 if (value instanceof String) {
421  0 String s = (String) value;
422  0 switch (dataType) {
423  0 case STRING:
424  0 v = new Data.StringValue(s);
425  0 break;
426  0 case BOOLEAN:
427  0 v = new Data.BooleanValue(Boolean.valueOf(s));
428  0 break;
429  0 case FLOAT:
430  0 v = new Data.FloatValue(Float.valueOf(s));
431  0 break;
432  0 case DATE:
433  0 DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
434  0 try {
435  0 v = new Data.DateValue(format.parse(s));
436    } catch (ParseException e) {
437  0 LOG.error("Unable to get default date value from metadata definition");
438    }
439  0 break;
440  0 case LONG:
441  0 if (!s.isEmpty()) {
442  0 v = new Data.LongValue(Long.valueOf(s));
443    }
444  0 break;
445  0 case DOUBLE:
446  0 v = new Data.DoubleValue(Double.valueOf(s));
447  0 break;
448  0 case INTEGER:
449  0 v = new Data.IntegerValue(Integer.valueOf(s));
450  0 break;
451    }
452    } else {
453  81 v = convertDefaultValue(value);
454    }
455   
456  81 return v;
457    }
458   
 
459  81 toggle protected Value convertDefaultValue(Object value) {
460  81 Value v = null;
461   
462  81 if (value instanceof String) {
463  0 v = new Data.StringValue((String) value);
464  81 } else if (value instanceof Boolean) {
465  0 v = new Data.BooleanValue((Boolean) value);
466  81 } else if (value instanceof Integer) {
467  0 v = new Data.IntegerValue((Integer) value);
468  81 } else if (value instanceof Double) {
469  0 v = new Data.DoubleValue((Double) value);
470  81 } else if (value instanceof Long) {
471  0 v = new Data.LongValue((Long) value);
472  81 } else if (value instanceof Short) {
473  0 v = new Data.ShortValue((Short) value);
474  81 } else if (value instanceof Float) {
475  0 v = new Data.FloatValue((Float) value);
476    }
477   
478  81 return v;
479    }
480   
 
481  81 toggle protected DataType convertDictionaryDataType(org.kuali.student.common.dictionary.dto.DataType dataType) {
482  81 switch (dataType) {
483  65 case STRING:
484  65 return DataType.STRING;
485  0 case BOOLEAN:
486  0 return DataType.BOOLEAN;
487  0 case INTEGER:
488  0 return DataType.INTEGER;
489  0 case FLOAT:
490  0 return DataType.FLOAT;
491  0 case COMPLEX:
492  0 return DataType.DATA;
493  8 case DATE:
494  8 return DataType.DATE;
495  8 case DOUBLE:
496  8 return DataType.DOUBLE;
497  0 case LONG:
498  0 return DataType.LONG;
499    }
500   
501  0 return null;
502    }
503   
 
504  2 toggle public void setUiLookupContext(String uiLookupContext) {
505  2 this.uiLookupContext = uiLookupContext;
506  2 init();
507   
508    }
509   
 
510  2 toggle @SuppressWarnings("unchecked")
511    private void init() {
512  2 ApplicationContext ac = new ClassPathXmlApplicationContext(uiLookupContext);
513   
514  2 Map<String, UILookupConfig> beansOfType = (Map<String, UILookupConfig>) ac.getBeansOfType(UILookupConfig.class);
515  2 lookupObjectStructures = new ArrayList<UILookupConfig>();
516  2 for (UILookupConfig objStr : beansOfType.values()) {
517  4 lookupObjectStructures.add(objStr);
518    }
519  2 System.out.println("UILookup loaded");
520    }
521   
 
522  20 toggle private String calcSimpleName(String objectKey) {
523  20 int lastDot = objectKey.lastIndexOf(".");
524  20 if (lastDot == -1) {
525  20 return objectKey;
526    }
527  0 return objectKey.substring(lastDot + 1);
528   
529    }
530   
 
531  20 toggle private boolean matchesObjectKey(String objectKey, String path) {
532  20 String simpleName = calcSimpleName(objectKey);
533  20 if (path.toLowerCase().startsWith(simpleName.toLowerCase())) {
534    // System.out.println ("matchesObjectKey: is TRUE for " + objectKey + " and " + path);
535  14 return true;
536    }
537    // System.out.println ("matchesObjectKey: is FALSE for " + objectKey + " and " + path);
538  6 return false;
539    }
540   
 
541  14 toggle private boolean matchesType(String paramType, String lookupType) {
542    // both null
543  14 if (paramType == null && lookupType == null) {
544  0 return true;
545    }
546    // not asking for type specific but the lookup defnition is type specific then
547    // no match
548  14 if (paramType == null && lookupType != null) {
549  4 return false;
550    }
551    // if looking for type specific but the lookup is not specific then
552    // take as default
553    // If configuration has both a null type (i.e. default) AND has a type
554    // specific one the type specific one has to be entered into the configuration
555    // file first so it is found first
556  10 if (paramType != null && lookupType == null) {
557  0 return true;
558    }
559  10 if (paramType.equalsIgnoreCase(lookupType)) {
560    // System.out.println ("matchesType: is TRUE for " + paramType + " and " + lookupType);
561  5 return true;
562    }
563    // System.out.println ("matchesType: is FALSE for " + paramType + " and " + lookupType);
564  5 return false;
565    }
566   
 
567  15 toggle private void addLookupstoMetadata(String objectKey, Metadata metadata, String type) {
568  15 if (lookupObjectStructures != null) {
569  10 for (UILookupConfig lookup : lookupObjectStructures) {
570  20 if (!matchesObjectKey(objectKey, lookup.getPath())) {
571  6 continue;
572    }
573  14 if (!matchesType(type, lookup.getType())) {
574  9 continue;
575    }
576    // TODO: figure out why path=courseInfo.creditOptions.type matches any structure that has a type on it so
577    // that lookup gets returned for all types
578  5 Map<String, Metadata> parsedMetadataMap = metadata.getProperties();
579  5 Metadata parsedMetadata = null;
580  5 String parsedMetadataKey = "";
581  5 String lookupFieldPath = lookup.getPath();
582  5 String[] lookupPathTokens = getPathTokens(lookupFieldPath);
583  10 for (int i = 1; i < lookupPathTokens.length; i++) {
584  5 if (parsedMetadataMap == null) {
585  0 break;
586    }
587  5 if (i == lookupPathTokens.length - 1) {
588    // get the metadata on the last path key token
589  5 parsedMetadata = parsedMetadataMap.get(lookupPathTokens[i]);
590  5 parsedMetadataKey = parsedMetadataKey + "." + lookupPathTokens[i];
591    }
592  5 if (parsedMetadataMap.get(lookupPathTokens[i]) != null) {
593  5 parsedMetadataMap = parsedMetadataMap.get(lookupPathTokens[i]).getProperties();
594  0 } else if (parsedMetadataMap.get("*") != null) {
595    // Lookup wildcard in case of unbounded elements in metadata.
596  0 parsedMetadataMap = parsedMetadataMap.get("*").getProperties();
597  0 i--;
598    }
599   
600    }
601  5 if (parsedMetadata != null) {
602    // System.out.println ("addLookupstoMetadata:" + parsedMetadataKey + " was found as a match for " +
603    // lookup.getPath ());
604  5 UILookupData initialLookup = lookup.getInitialLookup();
605  5 if (initialLookup != null) {
606  5 mapLookupDatatoMeta(initialLookup);
607  5 parsedMetadata.setInitialLookup(mapLookupDatatoMeta(lookup.getInitialLookup()));
608    }
609  5 List<LookupMetadata> additionalLookupMetadata = null;
610  5 if (lookup.getAdditionalLookups() != null) {
611  0 additionalLookupMetadata = new ArrayList<LookupMetadata>();
612  0 for (UILookupData additionallookup : lookup.getAdditionalLookups()) {
613  0 additionalLookupMetadata.add(mapLookupDatatoMeta(additionallookup));
614    }
615  0 parsedMetadata.setAdditionalLookups(additionalLookupMetadata);
616    }
617    }
618    }
619    }
620    }
621   
 
622  10 toggle private LookupMetadata mapLookupDatatoMeta(UILookupData lookupData) {
623  10 LookupMetadata lookupMetadata = new LookupMetadata();
624  10 List<LookupParamMetadata> paramsMetadata;
625  10 BeanUtils.copyProperties(lookupData, lookupMetadata, new String[]{"widget", "usage", "widgetOptions", "params"});
626  10 if (lookupData.getWidget() != null) {
627  10 lookupMetadata.setWidget(org.kuali.student.common.assembly.data.LookupMetadata.Widget.valueOf(lookupData.getWidget().toString()));
628    }
629  10 if (lookupData.getUsage() != null) {
630  10 lookupMetadata.setUsage(org.kuali.student.common.assembly.data.LookupMetadata.Usage.valueOf(lookupData.getUsage().toString()));
631    }
632  10 if (lookupData.getWidgetOptions () != null) {
633  0 lookupMetadata.setWidgetOptions (new HashMap ());
634  0 for (UILookupData.WidgetOption wo: lookupData.getWidgetOptions ().keySet ()) {
635  0 String value = lookupData.getWidgetOptions ().get (wo);
636  0 LookupMetadata.WidgetOption key = LookupMetadata.WidgetOption.valueOf(wo.toString());
637  0 lookupMetadata.getWidgetOptions ().put (key, value);
638    }
639    }
640  10 if (lookupData.getParams() != null) {
641  10 paramsMetadata = new ArrayList<LookupParamMetadata>();
642  10 for (CommonLookupParam param : lookupData.getParams()) {
643  50 paramsMetadata.add(mapLookupParamMetadata(param));
644    }
645  10 lookupMetadata.setParams(paramsMetadata);
646    }
647    // WidgetOptions is not used as of now. So not setting it into metadata.
648  10 return lookupMetadata;
649    }
650   
 
651  50 toggle private LookupParamMetadata mapLookupParamMetadata(CommonLookupParam param) {
652  50 LookupParamMetadata paramMetadata = new LookupParamMetadata();
653  50 BeanUtils.copyProperties(param, paramMetadata, new String[]{"childLookup", "dataType", "writeAccess", "usage", "widget"});
654  50 if (param.getChildLookup() != null) {
655  0 paramMetadata.setChildLookup(mapLookupDatatoMeta((UILookupData) param.getChildLookup()));
656    }
657  50 if (param.getDataType() != null) {
658  50 paramMetadata.setDataType(org.kuali.student.common.assembly.data.Data.DataType.valueOf(param.getDataType().toString()));
659    }
660  50 if (param.getWriteAccess() != null) {
661  40 paramMetadata.setWriteAccess(org.kuali.student.common.assembly.data.Metadata.WriteAccess.valueOf(param.getWriteAccess().toString()));
662    }
663  50 if (param.getUsage() != null) {
664  0 paramMetadata.setUsage(org.kuali.student.common.assembly.data.LookupMetadata.Usage.valueOf(param.getUsage().toString()));
665    }
666  50 if (param.getWidget() != null) {
667  0 paramMetadata.setWidget(org.kuali.student.common.assembly.data.LookupParamMetadata.Widget.valueOf(param.getWidget().toString()));
668    }
669   
670  50 return paramMetadata;
671    }
672   
 
673  5 toggle private static String[] getPathTokens(String fieldPath) {
674  5 return (fieldPath != null && fieldPath.contains(".") ? fieldPath.split("\\.") : new String[]{fieldPath});
675    }
676    }