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