1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.common.assembly.dictionary.old;
17
18 import java.text.DateFormat;
19 import java.text.ParseException;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.log4j.Logger;
27 import org.kuali.student.common.assembly.data.ConstraintMetadata;
28 import org.kuali.student.common.assembly.data.Data;
29 import org.kuali.student.common.assembly.data.Metadata;
30 import org.kuali.student.common.assembly.data.Data.DataType;
31 import org.kuali.student.common.assembly.data.Data.Value;
32 import org.kuali.student.common.assembly.data.Metadata.WriteAccess;
33 import org.kuali.student.common.dictionary.old.dto.ConstraintDescriptor;
34 import org.kuali.student.common.dictionary.old.dto.ConstraintSelector;
35 import org.kuali.student.common.dictionary.old.dto.Field;
36 import org.kuali.student.common.dictionary.old.dto.FieldDescriptor;
37 import org.kuali.student.common.dictionary.old.dto.ObjectStructure;
38 import org.kuali.student.common.dictionary.old.dto.State;
39 import org.kuali.student.common.dictionary.old.dto.Type;
40 import org.kuali.student.common.dictionary.service.old.DictionaryService;
41 import org.springframework.context.ConfigurableApplicationContext;
42 import org.springframework.context.support.ClassPathXmlApplicationContext;
43 import org.springframework.util.StringUtils;
44
45
46
47
48
49
50
51
52
53
54
55
56 @Deprecated
57 public class MetadataServiceImpl {
58 final Logger LOG = Logger.getLogger(MetadataServiceImpl.class);
59
60 private Map<String, Object> metadataRepository = null;
61
62 private Map<String, DictionaryService> dictionaryServiceMap;
63
64 private static class RecursionCounter{
65 public static final int MAX_DEPTH = 4;
66
67 private Map<String, Integer> recursions = new HashMap<String, Integer>();
68
69 public int increment(String objectName){
70 Integer hits = recursions.get(objectName);
71
72 if (hits == null){
73 hits = new Integer(1);
74 } else {
75 hits++;
76 }
77 recursions.put(objectName, hits);
78 return hits;
79 }
80
81 public int decrement(String objectName){
82 Integer hits = recursions.get(objectName);
83 if (hits >= 1){
84 hits--;
85 }
86
87 recursions.put(objectName, hits);
88 return hits;
89 }
90 }
91
92
93
94
95
96
97 public MetadataServiceImpl(String metadataContext){
98 init(metadataContext, (DictionaryService[])null);
99 }
100
101 public MetadataServiceImpl(DictionaryService...dictionaryServices){
102 init(null, dictionaryServices);
103 }
104
105 public MetadataServiceImpl(String metadataContext, DictionaryService...dictionaryServices){
106 init(metadataContext, dictionaryServices);
107 }
108
109 @SuppressWarnings("unchecked")
110 private void init(String metadataContext, DictionaryService...dictionaryServices){
111 if (metadataContext != null){
112 String[] locations = StringUtils.tokenizeToStringArray(metadataContext, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
113 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(locations);
114
115 Map<String, DataObjectStructure> beansOfType = (Map<String, DataObjectStructure>) context.getBeansOfType(DataObjectStructure.class);
116 metadataRepository = new HashMap<String, Object>();
117 for (DataObjectStructure dataObjStr : beansOfType.values()){
118 metadataRepository.put(dataObjStr.getName(), getProperties(dataObjStr, new RecursionCounter()));
119 }
120 }
121
122 if (dictionaryServices != null){
123 this.dictionaryServiceMap = new HashMap<String, DictionaryService>();
124 for (DictionaryService d:dictionaryServices){
125 List<String> objectTypes = d.getObjectTypes();
126 for(String objectType:objectTypes){
127 dictionaryServiceMap.put(objectType, d);
128 }
129 }
130 }
131
132 }
133
134
135
136
137
138
139
140
141
142 @SuppressWarnings("unchecked")
143 public Metadata getMetadata(String objectKey, String type, String state){
144 if (metadataRepository == null || metadataRepository.get(objectKey) == null){
145 return getMetadataFromDictionaryService(objectKey, type, state);
146 } else {
147 Metadata metadata = new Metadata ();
148 metadata.setWriteAccess(WriteAccess.ALWAYS);
149 metadata.setOnChangeRefreshMetadata(false);
150 metadata.setDataType(DataType.DATA);
151
152 metadata.setProperties((Map<String, Metadata>)metadataRepository.get(objectKey));
153
154
155 return new Metadata(metadata);
156 }
157 }
158
159
160
161
162
163
164
165 protected void loadProperties(Map<String, Metadata> properties, List<DataFieldDescriptor> fields, RecursionCounter counter){
166
167 for (DataFieldDescriptor field:fields){
168 Metadata metadata = new Metadata();
169 metadata.setWriteAccess(WriteAccess.valueOf(field.getWriteAccess()));
170 metadata.setDataType(DataType.valueOf(field.getDataType()));
171 metadata.setAdditionalLookups(field.getAdditionalLookups());
172 metadata.setLookupContextPath(field.getLookupContextPath());
173
174 metadata.setNonServerConstraints(field.getConstraints());
175 metadata.setName(field.getName());
176 metadata.setCanEdit(field.isCanEdit());
177 metadata.setCanView(field.isCanView());
178 metadata.setCanUnmask(field.isCanUnmask());
179 metadata.setDefaultValue(convertDefaultValue(metadata.getDataType(), field.getDefaultValue()));
180 metadata.setInitialLookup(field.getInitialLookup());
181
182 if (isRepeating(field)){
183 Metadata repeatingMetadata = new Metadata();
184 metadata.setDataType(DataType.LIST);
185
186 repeatingMetadata.setWriteAccess(WriteAccess.ALWAYS);
187 repeatingMetadata.setOnChangeRefreshMetadata(false);
188 repeatingMetadata.setDataType(DataType.valueOf(field.getDataType()));
189
190 if (field.getDataObjectStructure() != null){
191 repeatingMetadata.setProperties(getProperties(field.getDataObjectStructure(), counter));
192 }
193
194 Map<String, Metadata> repeatingProperty = new HashMap<String, Metadata>();
195 repeatingProperty.put("*", repeatingMetadata);
196 metadata.setProperties(repeatingProperty);
197 } else if (field.getDataObjectStructure() != null){
198 metadata.setProperties(getProperties(field.getDataObjectStructure(), counter));
199 }
200
201 properties.put(field.getName(), metadata);
202 }
203 }
204
205
206
207
208
209
210
211 protected boolean isRepeating(DataFieldDescriptor field){
212 if (field.getConstraints() != null) {
213 for (ConstraintMetadata c : field.getConstraints()) {
214 if (c.getId() != null && c.getId().equals("repeating")) {
215 return true;
216 }
217 }
218 }
219 return false;
220 }
221
222 @SuppressWarnings("unchecked")
223 protected Map<String, Metadata> getProperties(DataObjectStructure dataObjectStructure, RecursionCounter counter){
224 String objectId = dataObjectStructure.getName();
225 int hits = counter.increment(objectId);
226
227 Map<String, Metadata> properties = null;
228
229 if (hits == 1 && metadataRepository.containsKey(objectId)){
230 properties = (Map<String, Metadata>)metadataRepository.get(objectId);
231 } else if (hits < RecursionCounter.MAX_DEPTH){
232 properties = new HashMap<String, Metadata>();
233 if (hits == 1){
234 metadataRepository.put(objectId, properties);
235 }
236 loadProperties(properties, dataObjectStructure.getFields(), counter);
237 }
238
239 counter.decrement(objectId);
240 return properties;
241 }
242
243
244
245
246
247
248
249
250
251
252
253 protected Metadata getMetadataFromDictionaryService(String objectKey, String type, String state){
254
255 Metadata metadata = new Metadata();
256
257 ObjectStructure objectStructure = getObjectStructure(objectKey);
258 State objectState = getObjectState(objectStructure, type, state);
259
260 ConstraintDescriptor constraintDescriptor = objectState.getConstraintDescriptor();
261 metadata.setNonServerConstraints(copyConstraints(constraintDescriptor));
262
263 List<Field> fields = objectState.getField();
264 metadata.setProperties(getProperties(fields, type, state));
265
266 metadata.setWriteAccess(WriteAccess.ALWAYS);
267 metadata.setDataType(DataType.DATA);
268
269 return metadata;
270 }
271
272
273
274
275
276
277
278
279
280 private Map<String, Metadata> getProperties(List<Field> fields, String type, String state){
281 Map<String, Metadata> properties = new HashMap<String, Metadata>();
282
283 for (Field field:fields){
284 FieldDescriptor fd = field.getFieldDescriptor();
285
286 Metadata metadata = new Metadata();
287 metadata.setWriteAccess(WriteAccess.ALWAYS);
288 metadata.setDataType(convertDictionaryDataType(fd.getDataType()));
289 metadata.setNonServerConstraints(copyConstraints(field.getConstraintDescriptor()));
290
291
292
293 Map<String, Metadata> nestedProperties = null;
294 if (fd.getDataType().equals("complex")){
295 ObjectStructure objectStructure;
296 if (fd.getObjectStructure() != null){
297 objectStructure = fd.getObjectStructure();
298 } else {
299 String objectKey = fd.getObjectStructureRef();
300 objectStructure = getObjectStructure(objectKey);
301 }
302
303 State objectState = getObjectState(objectStructure, type, state);
304 nestedProperties = getProperties(objectState.getField(), type, state);
305
306
307
308
309 }
310
311
312 if (isRepeating(field)){
313 Metadata repeatingMetadata = new Metadata();
314 metadata.setDataType(DataType.LIST);
315
316 repeatingMetadata.setWriteAccess(WriteAccess.ALWAYS);
317 repeatingMetadata.setOnChangeRefreshMetadata(false);
318 repeatingMetadata.setDataType(convertDictionaryDataType(fd.getDataType()));
319
320 if (nestedProperties != null){
321 repeatingMetadata.setProperties(nestedProperties);
322 }
323
324 Map<String, Metadata> repeatingProperty = new HashMap<String, Metadata>();
325 repeatingProperty.put("*", repeatingMetadata);
326 metadata.setProperties(repeatingProperty);
327 } else if (nestedProperties != null){
328 metadata.setProperties(nestedProperties);
329 }
330
331 properties.put(fd.getName(), metadata);
332
333 }
334
335 return properties;
336 }
337
338
339
340
341
342
343
344
345 protected boolean isRepeating(Field field){
346 if (field.getConstraintDescriptor() != null && field.getConstraintDescriptor().getConstraint() != null){
347 for (ConstraintSelector c:field.getConstraintDescriptor().getConstraint()){
348 if (c.getKey().equals("repeating")){
349 return true;
350 }
351 }
352 }
353 return false;
354 }
355
356
357
358
359
360
361
362 protected ObjectStructure getObjectStructure(String objectKey){
363 DictionaryService dictionaryService = dictionaryServiceMap.get(objectKey);
364
365 return dictionaryService.getObjectStructure(objectKey);
366 }
367
368
369
370
371
372
373
374
375
376 protected State getObjectState(ObjectStructure objectStructure, String type, String state){
377
378
379 for (Type t:objectStructure.getType()){
380 if (t.getKey().equals(type)){
381 for (State s:t.getState()){
382 if (s.getKey().equals(state)){
383 return s;
384 }
385 }
386 }
387 }
388
389 return null;
390 }
391
392 protected List<ConstraintMetadata> copyConstraints(ConstraintDescriptor constraintDescriptor){
393 List<ConstraintMetadata> constraints = null;
394
395 if (constraintDescriptor != null && constraintDescriptor.getConstraint() != null){
396 constraints = new ArrayList<ConstraintMetadata>();
397
398
399 for (ConstraintSelector dictConstraint:constraintDescriptor.getConstraint()){
400 ConstraintMetadata constraintMetadata = new ConstraintMetadata();
401
402 constraintMetadata.setId(dictConstraint.getKey());
403 if (dictConstraint.getMaxLength() != null){
404 constraintMetadata.setMaxLength(Integer.valueOf(dictConstraint.getMaxLength()));
405 }
406 constraintMetadata.setMinLength(dictConstraint.getMinLength());
407 constraintMetadata.setMinOccurs(dictConstraint.getMinOccurs());
408 constraintMetadata.setMinValue(dictConstraint.getMinValue());
409
410 if (dictConstraint.getValidChars() != null){
411 constraintMetadata.setValidChars(dictConstraint.getValidChars().getValue());
412 }
413
414
415
416
417
418 constraints.add(constraintMetadata);
419 }
420 }
421
422 return constraints;
423 }
424
425
426
427
428
429
430
431 protected Value convertDefaultValue(DataType dataType, Object value){
432 Value v = null;
433 if (value instanceof String){
434 String s = (String)value;
435 switch (dataType){
436 case STRING:
437 value = new Data.StringValue(s);
438 break;
439 case BOOLEAN:
440 value = new Data.BooleanValue(Boolean.valueOf(s));
441 break;
442 case FLOAT:
443 value = new Data.FloatValue(Float.valueOf(s));
444 break;
445 case DATE:
446 DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
447 try {
448 value = new Data.DateValue(format.parse(s));
449 } catch (ParseException e) {
450 LOG.error("Unable to get default date value from metadata definition");
451 }
452 break;
453 case LONG:
454 if (!s.isEmpty()){
455 value = new Data.LongValue(Long.valueOf(s));
456 }
457 break;
458 case DOUBLE:
459 value = new Data.DoubleValue(Double.valueOf(s));
460 break;
461 case INTEGER:
462 value = new Data.IntegerValue(Integer.valueOf(s));
463 break;
464 }
465 }
466
467 return v;
468 }
469
470 protected DataType convertDictionaryDataType(String dataType){
471 if ("string".equals(dataType)){
472 return DataType.STRING;
473 } else if ("boolean".equals(dataType)){
474 return DataType.BOOLEAN;
475 } else if ("integer".equals(dataType)){
476 return DataType.INTEGER;
477 } else if ("datetime".equals(dataType)){
478 return DataType.DATE;
479 } else if ("complex".equals(dataType)){
480 return DataType.DATA;
481 }
482
483 return null;
484 }
485 }