View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.r1.common.assembly.data;
17  
18  import java.util.Date;
19  import java.util.List;
20  
21  import org.kuali.student.r1.common.validator.DateParser;
22  
23  /**
24   * 
25   * @author nwright
26   */
27  public class MetadataInterrogator {
28  
29  	public enum ConstraintIds {
30  		MULTI_LINE_TEXT("multi.line.text"), RICH_TEXT("rich.text");
31  		private final String id;
32  
33  		private ConstraintIds(final String id) {
34  			this.id = id;
35  		}
36  
37  		public String getId() {
38  			return this.id;
39  		}
40  	}
41  
42  	private Metadata meta;
43  
44  	public MetadataInterrogator(Metadata meta) {
45  		this.meta = meta;
46  	}
47  
48  	/**
49  	 * Returns true if the metadata contains the specified constraint
50  	 */
51  	public boolean hasConstraint(String id) {
52  		return hasConstraint(meta, id);
53  	}
54  
55  
56  	/**
57  	 * checks if is required
58  	 * 
59  	 * @return true if any minOccurs > 1
60  	 */
61  	public boolean isRequired() {
62  		return isRequired(meta);
63  	}
64  
65  	/**
66  	 * get the largest min occurs value
67  	 * 
68  	 * @return null if none specified
69  	 */
70  	public Integer getLargestMinOccurs() {
71  		return getLargestMinOccurs(meta);
72  	}
73  
74  	/**
75  	 * checks if this field is a repeating field
76  	 * 
77  	 * @return true if the smallest maxOccurs is > 1
78  	 */
79  	public boolean isRepeating() {
80  		return isRepeating(meta);
81  	}
82  
83  	/**
84  	 * checks if this field is a repeating field
85  	 * 
86  	 * @return true if the smallest maxOccurs is > 1
87  	 */
88  	public Integer getSmallestMaxOccurs() {
89  		return getSmallestMaxOccurs(meta);
90  	}
91  
92  	/**
93  	 * get the largest min occurs value
94  	 * 
95  	 * @return null if none specified
96  	 */
97  	public Integer getLargestMinLength() {
98  		return getLargestMinLength(meta);
99  	}
100 
101 	public Integer getSmallestMaxLength() {
102 		return getSmallestMaxLength(meta);
103 	}
104 
105 	public boolean isMultilined() {
106 		return isMultilined(meta);
107 	}
108 
109 	
110 	/**
111 	 * Returns true if the metadata contains the specified constraint
112 	 */
113 	public static boolean hasConstraint(Metadata meta, ConstraintIds id) {
114 		return hasConstraint(meta, id.getId());
115 	}
116 	/**
117 	 * Returns true if the metadata contains the specified constraint
118 	 */
119 	public static boolean hasConstraint(Metadata meta, String id) {
120 		boolean result = false;
121 		if (meta != null && meta.getConstraints() != null) {
122 			result = containsConstraint(meta.getConstraints(), id);
123 		}
124 		return result;
125 	}
126 
127 	private static boolean containsConstraint(List<ConstraintMetadata> constraints,
128 			String id) {
129 		boolean result = false;
130 		if (constraints != null) {
131 			for (ConstraintMetadata con : constraints) {
132 				if ((con.getId() != null && con.getId().equals(id))
133 						|| containsConstraint(con.getChildConstraints(), id)) {
134 					result = true;
135 					break;
136 				}
137 			}
138 		}
139 		return result;
140 	}
141 
142 	/**
143 	 * checks if is required
144 	 * 
145 	 * @return true if any minOccurs > 1
146 	 */
147 	public static boolean isRequired(Metadata meta) {
148 		if (meta == null) {
149 			return false;
150 		}
151 		Integer largestMinOccurs = getLargestMinOccurs(meta);
152 		// no min occurs specified so not required
153 		if (largestMinOccurs == null) {
154 			return false;
155 		}
156 		if (largestMinOccurs >= 1) {
157 			return true;
158 		}
159 		return false;
160 	}
161 
162 	/**
163 	 * Use to determine if the field is required for the next state.
164 	 * 
165 	 * @param meta
166 	 * @return
167 	 */
168 	public static boolean isRequiredForNextState(Metadata meta){
169 		boolean required = false;
170 		
171 		if(meta == null){
172 			return false;
173 		}
174 		//This flag is only set when using the new dictionary, in which case there should
175 		//never be more than one constraint.
176 		if (meta.getConstraints() != null && meta.getConstraints().size() == 1){
177 			ConstraintMetadata constraint =  meta.getConstraints().get(0);
178 			required = constraint.isRequiredForNextState();
179 		}
180 		
181 		return required;
182 	}
183 	
184 	/**
185 	 * Use to determine if the field is required for the next state.
186 	 * 
187 	 * @param meta
188 	 * @return
189 	 */
190 	public static String getNextState(Metadata meta){
191 		String state = null;
192 		
193 		if(meta == null){
194 			return state;
195 		}
196 		//This flag is only set when using the new dictionary, in which case there should
197 		//never be more than one constraint.
198 		if (meta.getConstraints() != null && meta.getConstraints().size() == 1){
199 			ConstraintMetadata constraint =  meta.getConstraints().get(0);
200 			state = constraint.getNextState();
201 		}
202 		
203 		return state;
204 	}
205 	
206 	/**
207 	 * get the largest min occurs value
208 	 * 
209 	 * @return null if none specified
210 	 */
211 	public static Integer getLargestMinOccurs(Metadata meta) {
212 		if (meta == null) {
213 			return null;
214 		}
215 		Integer largestMinOccurs = null;
216 		// TODO: worry aboutg special validators
217 		// TODO: worry about how this applies to non-strings?
218 		for (ConstraintMetadata cons : meta.getConstraints()) {
219 			if (cons.getMinOccurs() != null) {
220 				if (largestMinOccurs == null) {
221 					largestMinOccurs = cons.getMinOccurs();
222 				} else if (cons.getMinOccurs() > largestMinOccurs) {
223 					largestMinOccurs = cons.getMinOccurs();
224 				}
225 			}
226 		}
227 		return largestMinOccurs;
228 	}
229 
230 	/**
231 	 * checks if this field is a repeating field
232 	 * 
233 	 * @return true if the smallest maxOccurs is > 1
234 	 */
235 	public static boolean isRepeating(Metadata meta) {
236 		if (meta == null) {
237 			return false;
238 		}
239 		Integer smallestMaxOccurs = getSmallestMaxOccurs(meta);
240 		if (hasRepeatingConstraint(meta) ||
241 				(smallestMaxOccurs != null && smallestMaxOccurs > 1)) {
242 			return true;
243 		}
244 		return false;
245 	}
246 	
247 	private static boolean hasRepeatingConstraint(Metadata meta) {
248 		boolean isRepeating = false;
249 
250 		for (ConstraintMetadata cons : meta.getConstraints()) {
251 			if ("repeating".equals(cons.getId())){
252 				isRepeating = true;
253 			}
254 		}
255 		return isRepeating;
256 	}
257 
258 	/**
259 	 * Returns the smallest max occurs
260 	 * 
261 	 * @return 
262 	 * 
263 	 * Returns the smallest of all maxOccurs, if maxOccurs defined in constraints. 
264 	 * Returns -1, indicating unbounded repeating field, if repeating constraint defined & maxOccurs not defined. 
265 	 * Returns null, indicating that this is a non-repeating field.
266 	 */
267 	public static Integer getSmallestMaxOccurs(Metadata meta) {
268 		if (meta == null) {
269 			return null;
270 		}
271 		Integer smallestMaxOccurs = null;
272 		boolean isRepeating = false;
273 
274 		for (ConstraintMetadata cons : meta.getConstraints()) {
275 			if ("repeating".equals(cons.getId())){
276 				isRepeating = true;
277 			}
278 			if (cons.getMaxOccurs() != null) {
279 				if (smallestMaxOccurs == null) {
280 					smallestMaxOccurs = cons.getMaxOccurs();
281 				} else if (cons.getMaxOccurs() < smallestMaxOccurs) {
282 					smallestMaxOccurs = cons.getMaxOccurs();
283 				}
284 			}
285 		}
286 		
287 		if (isRepeating && smallestMaxOccurs == null){
288 			smallestMaxOccurs = -1;
289 		}
290 		
291 		return smallestMaxOccurs;
292 	}
293 
294 	/**
295 	 * get the largest min occurs value
296 	 * 
297 	 * @return null if none specified
298 	 */
299 	public static Integer getLargestMinLength(Metadata meta) {
300 		if (meta == null) {
301 			return null;
302 		}
303 		Integer largestMinLength = null;
304 		// TODO: worry aboutg special validators
305 		// TODO: worry about how this applies to non-strings?
306 		for (ConstraintMetadata cons : meta.getConstraints()) {
307 			if (cons.getMinLength() != null) {
308 				if (largestMinLength == null) {
309 					largestMinLength = cons.getMinLength();
310 				} else if (cons.getMinLength() > largestMinLength) {
311 					largestMinLength = cons.getMinLength();
312 				}
313 			}
314 		}
315 		return largestMinLength;
316 	}
317 
318 	public static Integer getSmallestMaxLength(Metadata meta) {
319 		if (meta == null) {
320 			return null;
321 		}
322 		Integer smallestMaxLength = null;
323 		// TODO: worry aboutg special validators
324 		// TODO: worry about how this applies to non-strings?
325 		for (ConstraintMetadata cons : meta.getConstraints()) {
326 			if (cons.getMaxLength() != null) {
327 				if (smallestMaxLength == null) {
328 					smallestMaxLength = cons.getMaxLength();
329 				} else if (cons.getMaxLength() < smallestMaxLength) {
330 					smallestMaxLength = cons.getMaxLength();
331 				}
332 			}
333 		}
334 		return smallestMaxLength;
335 	}
336 
337 	public static boolean isMultilined(Metadata meta) {
338 		if (meta == null) {
339 			return false;
340 		}
341 		// TODO: worry about hard coding ids
342 		boolean result = (hasConstraint(meta, "rich.text") || hasConstraint(meta, "multi.line.text")) 
343 			&& !(hasConstraint(meta, "single.line.text") || hasConstraint(meta, "code") || hasConstraint(meta, "no.linefeeds"));
344 		
345 		// TODO: Worry about hard coding the cut-off point
346 		if (!result) {
347 			Integer maxLength = getSmallestMaxLength(meta);
348 			if (maxLength != null) {
349 				if (maxLength > 150) {
350 					result = true;
351 				}
352 			}
353 		}
354 		return result;
355 	}
356 
357 	
358 	public static Long getLargestMinValue(Metadata meta) {
359 		if (meta == null) {
360 			return null;
361 		}
362 		Long result = null;
363 		for (ConstraintMetadata cons : meta.getConstraints()) {
364 			Long min = tryParseLong(cons.getMinValue());
365 			if (min != null) {
366 				if (result == null || min > result) {
367 					result = min;
368 				}
369 			}
370 		}
371 		return result;
372 	}
373 
374 	public static Long getSmallestMaxValue(Metadata meta) {
375 		if (meta == null) {
376 			return null;
377 		}
378 		Long result = null;
379 		for (ConstraintMetadata cons : meta.getConstraints()) {
380 			Long max = tryParseLong(cons.getMaxValue());
381 			if (max != null) {
382 				if (result == null || max < result) {
383 					result = max;
384 				}
385 			}
386 		}
387 		return result;
388 	}
389 
390 	
391 	public static Double getLargestMinValueDouble(Metadata meta) {
392 		if (meta == null) {
393 			return null;
394 		}
395 		Double result = null;
396 		for (ConstraintMetadata cons : meta.getConstraints()) {
397 			Double min = tryParseDouble(cons.getMinValue());
398 			if (min != null) {
399 				if (result == null || min > result) {
400 					result = min;
401 				}
402 			}
403 		}
404 		return result;
405 	}
406 
407 	public static Double getSmallestMaxValueDouble(Metadata meta) {
408 		if (meta == null) {
409 			return null;
410 		}
411 		Double result = null;
412 		for (ConstraintMetadata cons : meta.getConstraints()) {
413 			Double max = tryParseDouble(cons.getMaxValue());
414 			if (max != null) {
415 				if (result == null || max < result) {
416 					result = max;
417 				}
418 			}
419 		}
420 		return result;
421 	}
422 
423 	public static Date getLargestMinValueDate(Metadata meta, DateParser parser, Object dataValue) {
424 		if (meta == null) {
425 			return null;
426 		}
427 		Date result = null;
428 		for (ConstraintMetadata cons : meta.getConstraints()) {
429 			Date min = tryParseDate(cons.getMinValue(), parser);
430 			if (min != null) {
431 				if (result == null || min.getTime() > result.getTime()) {
432 					result = min;
433 				}
434 			}
435 		}
436 		if (dataValue != null && dataValue instanceof Date){
437 			if (result == null || (((Date)dataValue).getTime() > result.getTime())){
438 				result = (Date)dataValue;
439 			}
440 		}
441 		return result;
442 	}
443 
444 	public static Date getSmallestMaxValueDate(Metadata meta, DateParser parser, Object dataValue) {
445 		if (meta == null) {
446 			return null;
447 		}
448 		Date result = null;
449 		for (ConstraintMetadata cons : meta.getConstraints()) {
450 			Date max = tryParseDate(cons.getMaxValue(), parser);
451 			if (max != null) {
452 				if (result == null || max.getTime() < result.getTime()) {
453 					result = max;
454 				}
455 			}
456 		}
457 		if (dataValue != null && dataValue instanceof Date){
458 			if (result==null || (((Date)dataValue).getTime() < result.getTime())){
459 				result = (Date)dataValue;
460 			}
461 		}
462 		return result;
463 	}
464 	
465 	private static Long tryParseLong(String s) {
466 		Long result = null;
467 		
468 		if (s != null) {
469 			try {
470 				result = Long.valueOf(s);
471 			} catch (Exception e) {
472 				// do nothing
473 			}
474 		}
475 		
476 		return result;
477 	}
478 	
479 	private static Double tryParseDouble(String s) {
480 		Double result = null;
481 		
482 		if (s != null) {
483 			try {
484 				result = Double.valueOf(s);
485 			} catch (Exception e) {
486 				// do nothing
487 			}
488 		}
489 		
490 		return result;
491 	}
492 	
493 	private static Date tryParseDate(String s, DateParser parser) {
494 		Date result = null;
495 		
496 		if (s != null) {
497 			try {
498 				result = parser.parseDate(s);
499 			} catch (Exception e) {
500 				// do nothing
501 			}
502 		}
503 		
504 		return result;
505 	}
506 }