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  package org.kuali.student.r1.common.assembly.dictionary;
16  
17  import java.util.ArrayList;
18  import java.util.Collections;
19  import java.util.List;
20  import java.util.Set;
21  
22  import org.kuali.student.r1.common.assembly.data.ConstraintMetadata;
23  import org.kuali.student.r1.common.assembly.data.Data;
24  import org.kuali.student.r1.common.assembly.data.LookupMetadata;
25  import org.kuali.student.r1.common.assembly.data.LookupParamMetadata;
26  import org.kuali.student.r1.common.assembly.data.Metadata;
27  import org.kuali.student.r1.common.assembly.data.MetadataInterrogator;
28  
29  @Deprecated
30  public class MetadataFormatter {
31  
32  	private StringBuilder builder = new StringBuilder(5000);
33  	private Metadata structureMetadata;
34  	private String type;
35  	private String rowSeperator = "\n";
36  	private String colSeperator = "|";
37  	private String structureName;
38  	private int level;
39  //	private Map<String, Metadata> subStructuresToProcess = new LinkedHashMap<String, Metadata>();
40  	private Set<Metadata> structuresAlreadyProcessed;
41  	private MetadataFormatter parent;
42  
43  	public MetadataFormatter(String structureName, Metadata structureMetadata,
44  			String type, MetadataFormatter parent,
45  			Set<Metadata> structuresAlreadyProcessed, int level) {
46  		this.structureName = structureName;
47  		this.structureMetadata = structureMetadata;
48  		this.type = type;
49  		this.parent = parent;
50  		this.structuresAlreadyProcessed = structuresAlreadyProcessed;
51  		this.level = level;
52  	}
53  
54  	public String getStructureName() {
55  		return structureName;
56  	}
57  
58  	public MetadataFormatter getParent() {
59  		return parent;
60  	}
61  
62  	public String getRowSeperator() {
63  		return rowSeperator;
64  	}
65  
66  	public void setRowSeperator(String rowSeperator) {
67  		this.rowSeperator = rowSeperator;
68  	}
69  
70  	public String getColSeparator() {
71  		return colSeperator;
72  	}
73  
74  	public void setColSeparator(String separator) {
75  		this.colSeperator = separator;
76  	}
77  
78  	private String pad(String str, int size) {
79  		StringBuilder padStr = new StringBuilder(size);
80  		padStr.append(str);
81  		while (padStr.length() < size) {
82  			padStr.append(' ');
83  		}
84  		return padStr.toString();
85  	}
86  
87  	public String formatForWiki() {
88  		if (!this.structuresAlreadyProcessed.add(structureMetadata)) {
89  			return "";
90  		}
91  		if (level == 1) {
92  			builder.append(rowSeperator);
93  			// builder.append
94  			// ("======= start dump of object structure definition ========");
95  			builder.append(rowSeperator);
96  			String header = "h1. " + this.calcSimpleName(structureName);
97  			if (type != null) {
98  				header = "h2. " + type;
99  			}
100 			builder.append(header);
101 			builder.append("{anchor:" + structureName + "}");
102 			builder.append(rowSeperator);
103 			builder.append("The object key is " + structureName);
104 			builder.append(rowSeperator);
105 			builder.append("The type is " + type);
106 			builder.append(rowSeperator);
107 			builder.append(colSeperator);
108 			builder.append(colSeperator);
109 			builder.append("Field");
110 			builder.append(colSeperator);
111 			builder.append(colSeperator);
112 			builder.append("Required?");
113 			builder.append(colSeperator);
114 			builder.append(colSeperator);
115 			builder.append("DataType");
116 			builder.append(colSeperator);
117 			builder.append(colSeperator);
118 			builder.append("Length");
119 			builder.append(colSeperator);
120 			builder.append(colSeperator);
121 			builder.append("Dynamic");
122 			builder.append(colSeperator);
123 			builder.append(colSeperator);
124 			builder.append("Default");
125 			builder.append(colSeperator);
126 			builder.append(colSeperator);
127 			builder.append("Repeats?");
128 			builder.append(colSeperator);
129 			builder.append(colSeperator);
130 			builder.append("Valid Characters");
131 			builder.append(colSeperator);
132 			builder.append(colSeperator);
133 			builder.append("Lookup Widget");
134 			builder.append(colSeperator);
135 			builder.append(colSeperator);
136 			builder.append("Lookup");
137 			builder.append(colSeperator);
138 			builder.append(colSeperator);
139 			builder.append(rowSeperator);
140 		}
141 
142 		List<String> keys = new ArrayList<String>();
143 		keys.addAll(structureMetadata.getProperties().keySet());
144 		Collections.sort(keys);
145 		for (String key : keys) {
146    if (key.equalsIgnoreCase ("_runtimeData"))
147    {
148     continue;
149    }
150 			Metadata fieldMeta = structureMetadata.getProperties().get(key);
151 			builder.append(colSeperator);
152 			builder.append(calcFieldInfo (key, fieldMeta));
153 			builder.append(colSeperator);
154 			builder.append(pad(calcRequired(fieldMeta), 10));
155 			builder.append(colSeperator);
156 			builder.append(pad(calcDataType(fieldMeta), 25));
157 			builder.append(colSeperator);
158 			builder.append(pad(calcLength(fieldMeta), 15));
159 			builder.append(colSeperator);
160 			builder.append(pad(calcDynamic(fieldMeta), 7));
161 			builder.append(colSeperator);
162 			builder.append(pad(calcDefaultValue(fieldMeta), 15));
163 			builder.append(colSeperator);
164 			builder.append(calcRepeating(fieldMeta));
165 			builder.append(colSeperator);
166 			builder.append(calcValidChars(fieldMeta));
167 			builder.append(colSeperator);
168 			builder.append(calcWidget(fieldMeta));
169 			builder.append(colSeperator);
170 			builder.append(calcLookup(fieldMeta));
171 			builder.append(colSeperator);
172 			builder.append(rowSeperator);
173 			if (fieldMeta.getDataType().equals(Data.DataType.DATA)
174 					|| fieldMeta.getDataType().equals(Data.DataType.LIST)) {
175 				if (fieldMeta.getProperties() == null) {
176 					throw new IllegalArgumentException(
177 							fieldMeta.getName()
178 									+ " is DATA but does not have a sub-structure defined");
179 				}
180 				MetadataFormatter formatter = new MetadataFormatter(key,
181 						fieldMeta, null, this, structuresAlreadyProcessed,
182 						level + 1);
183 				builder.append(formatter.formatForWiki());
184 			}
185 		}
186 
187 		return builder.toString();
188 	}
189 
190 	private String calcDataType(Metadata fieldMeta) {
191 		if (fieldMeta.getDataType().equals(Data.DataType.LIST)) {
192 			StringBuilder type = new StringBuilder();
193 			type.append("LIST of ");
194 			String comma = "";
195 			for (String key : fieldMeta.getProperties().keySet()) {
196 				type.append(comma);
197 				type.append(fieldMeta.getProperties().get(key).getDataType()
198 						.toString());
199 				comma = ", ";
200 			}
201 			return type.toString();
202 		}
203 		return fieldMeta.getDataType().toString();
204 	}
205 
206 	private String calcDefaultValue(Metadata fieldMeta) {
207 		if (fieldMeta.getDefaultValue() != null) {
208 			return fieldMeta.getDefaultValue().toString();
209 		}
210 		return " ";
211 	}
212 
213 	private String calcDynamic(Metadata meta) {
214 		if (meta.isDynamic()) {
215 			return "dynamic";
216 		}
217 		return " ";
218 	}
219 
220  private String calcFieldInfo (String key, Metadata fieldMeta)
221  {
222   StringBuilder bldr = new StringBuilder (40);
223   bldr.append (pad(calcFullyQualifiedFieldName(key), 30));
224   if (fieldMeta.getLabelKey () != null)
225   {
226    bldr.append ("\\\\\n");
227    bldr.append ("Label: ");
228    bldr.append (fieldMeta.getLabelKey ());
229   }
230   return bldr.toString ();
231  }
232 
233 	public String calcFullyQualifiedFieldName(String fieldName) {
234 		if (parent == null) {
235 			return escapeWiki(fieldName);
236 		}
237 		return parent.calcFullyQualifiedFieldName(structureName) + "."
238 				+ escapeWiki(fieldName);
239 	}
240 
241 	private String calcSimpleName(String name) {
242 		if (name.lastIndexOf(".") != -1) {
243 			name = name.substring(name.lastIndexOf(".") + 1);
244 		}
245 		return name;
246 	}
247 
248 	private String calcNotSoSimpleName(String name) {
249 		if (name.lastIndexOf(".") == -1) {
250 			return name;
251 		}
252 		String simpleName = calcSimpleName(name);
253 		String fieldName = calcSimpleName(name.substring(0, name.length()
254 				- simpleName.length() - 1));
255 		return fieldName + "." + simpleName;
256 	}
257 
258 	private String calcRequired(Metadata fieldMeta) {
259 		for (ConstraintMetadata cons : fieldMeta.getConstraints()) {
260 			if (cons.getMaxOccurs() != null) {
261 				if (cons.getMaxOccurs() == 0) {
262 					return "NOT USED";
263 				}
264 			}
265 
266 			if (cons.getMinOccurs() != null) {
267 				if (cons.getMinOccurs() >= 1) {
268 					return "required";
269 				}
270 			}
271 		}
272 		return " ";
273 		// return "optional";
274 	}
275 
276 	private static final String LINK_TO_DEFINITIONS = "KULSTG:Formatted View of Base Dictionary#Valid Character Definitions";
277 
278 	private String calcValidChars(Metadata fieldMeta) {
279 		for (ConstraintMetadata cons : fieldMeta.getConstraints()) {
280 			if (cons.getValidChars() == null) {
281 				continue;
282 			}
283 			String validChars = escapeWiki(cons.getValidChars());
284 			String descr = "[" + "See" + "|" + LINK_TO_DEFINITIONS + "]"
285 					+ "\\\\\n" + validChars;
286 			return descr;
287 		}
288 		return " ";
289 	}
290 
291 	private String escapeWiki(String str) {
292 		StringBuilder bldr = new StringBuilder(str.length());
293 		boolean precededByBackSlash = false;
294 		for (int i = 0; i < str.length(); i++) {
295 			char c = str.charAt(i);
296 			switch (c) {
297 			case '\\':
298 			case '[':
299 			case '*':
300 			case ']':
301 			case '|':
302 				if (!precededByBackSlash) {
303 					bldr.append('\\');
304 				}
305 				break;
306 			default:
307 				break;
308 			}
309 			bldr.append(c);
310 			if (c == '\\') {
311 				precededByBackSlash = true;
312 			} else {
313 				precededByBackSlash = false;
314 			}
315 		}
316 		return bldr.toString();
317 	}
318 
319 	private String calcWidget(Metadata fieldMeta) {
320 		StringBuilder bldr = new StringBuilder();
321 		String comma = "";
322 		if (!fieldMeta.isCanEdit()) {
323 			bldr.append(comma);
324 			bldr.append("not editable");
325 			comma = ", ";
326 		}
327 		if (!fieldMeta.isCanView()) {
328 			bldr.append(comma);
329 			bldr.append("not viewable");
330 			comma = ", ";
331 		}
332 		if (!fieldMeta.isCanUnmask()) {
333 			bldr.append(comma);
334 			bldr.append("Not unmaskable");
335 			comma = ", ";
336 		}
337 		if (fieldMeta.getInitialLookup() != null) {
338 			bldr.append(comma);
339 			bldr.append(fieldMeta.getInitialLookup().getWidget());
340 			comma = ", ";
341 		}
342 		if (bldr.length() == 0) {
343 			bldr.append(" ");
344 		}
345 		return bldr.toString();
346 	}
347 
348 	private String calcLookup(Metadata fieldMeta) {
349   StringBuilder bldr = new StringBuilder ();
350 		if (fieldMeta.getInitialLookup() != null) {
351 		 bldr.append (calcLookup (fieldMeta.getInitialLookup ()));
352 		}
353    
354   if (fieldMeta.getAdditionalLookups () != null) {
355    if (fieldMeta.getAdditionalLookups ().size () > 0) {
356     if (fieldMeta.getInitialLookup() == null) {
357 		   bldr.append ("No initial lookup but...");
358 		  }
359 		  bldr.append("\\\\");
360 		  bldr.append("\n");   
361 		  bldr.append("\\\\");
362 		  bldr.append("\n");
363     bldr.append ("Additional Lookups:");
364 		  bldr.append("\\\\");
365 		  bldr.append("\n");
366    }
367    for (LookupMetadata lm : fieldMeta.getAdditionalLookups ())  {
368 		  bldr.append("\\\\");
369   		bldr.append("\n");
370     bldr.append (calcLookup (lm));
371     bldr.append("\\\\");
372 		  bldr.append("\n");
373    }  
374   }
375   if (bldr.length () == 0)
376   {
377    bldr.append (" ");
378   }
379   return bldr.toString ();
380  }
381 
382  private String calcLookup(LookupMetadata lm) {
383 		StringBuilder bldr = new StringBuilder();
384 		bldr.append(lm.getId());
385 //  if (lm.getUsage () != null) {
386 //   bldr.append (" usage " + lm.getUsage ());
387 //  }
388 		// this is the search description not the lookup description
389 		bldr.append (" - ");
390 		bldr.append (lm.getName());
391   bldr.append (" " + lm.getWidget ());
392   String and = " with option ";
393   if (lm.getWidgetOptions () != null) {
394    for (LookupMetadata.WidgetOption wo: lm.getWidgetOptions ().keySet ())
395    {
396     bldr.append (" and ");
397     bldr.append (wo);
398     bldr.append ("=");
399     bldr.append (lm.getWidgetOptions ().get (wo));
400    }
401   }
402 		and = "";
403 		bldr.append("\\\\\n");
404 		bldr.append("Implemented using search: ");
405 		String searchPage = calcWikiSearchPage(lm.getSearchTypeId());
406 		bldr.append("[" + lm.getSearchTypeId() + "|" + searchPage + "#"
407 				+ lm.getSearchTypeId() + "]");
408 		List<LookupParamMetadata> configuredParameters = filterConfiguredParams(lm
409 				.getParams());
410 		if (configuredParameters.size() > 0) {
411 			bldr.append("\\\\");
412 			bldr.append("\n");
413 			bldr.append(" where ");
414 			and = "";
415 			for (LookupParamMetadata param : configuredParameters) {
416 				bldr.append(and);
417 				and = " and ";
418 				bldr.append(param.getName());
419     bldr.append (" (" + param.getDataType () + ") ");
420 				bldr.append("=");
421 				if (param.getDefaultValueString() != null) {
422 					bldr.append(param.getDefaultValueString());
423 				}
424 				if (param.getDefaultValueList() != null) {
425 					String comma = "";
426 					for (String defValue : param.getDefaultValueList()) {
427 						bldr.append(comma);
428 						comma = ", ";
429 						bldr.append(defValue);
430 					}
431 				}
432 			}
433   }
434   List<LookupParamMetadata> userEnterableParameters = this.filterUserEnterableParams (lm
435 				.getParams());
436 		if (userEnterableParameters.size() > 0) {
437 			bldr.append("\\\\");
438 			bldr.append("\n");
439 			bldr.append(" and the user can enter: ");
440 			for (LookupParamMetadata param : userEnterableParameters) {
441 				bldr.append ("\\\\\n");
442 				bldr.append(param.getName());
443     bldr.append (" (" + param.getDataType () + ")");
444     if (param.getWidget () != null) {
445 				 bldr.append(" using widget ");
446      bldr.append (param.getWidget ());
447     }
448 				if (param.getDefaultValueString() != null) {
449 					bldr.append("defaulted to " + param.getDefaultValueString());
450 				}
451 				if (param.getDefaultValueList() != null) {
452 					String comma = "defaulted to ";
453 					for (String defValue : param.getDefaultValueList()) {
454 						bldr.append(comma);
455 						comma = ", ";
456 						bldr.append(defValue);
457 					}
458 				}
459     if (param.getChildLookup () != null)
460     {
461 			  bldr.append("\\\\");
462 			  bldr.append("\n");
463      bldr.append ("using a child lookup: ");
464 			  bldr.append("\\\\");
465 			  bldr.append("\n");
466      bldr.append (calcLookup (param.getChildLookup ()));
467     }
468    }
469 		}
470 		return bldr.toString();
471  }
472 
473 	private static final String PAGE_PREFIX = "Formatted View of ";
474 	private static final String PAGE_SUFFIX = " Searches";
475 
476 	private String calcWikiSearchPage(String searchType) {
477 		return PAGE_PREFIX + calcWikigPageAbbrev(searchType) + PAGE_SUFFIX;
478 	}
479 
480 	private String calcWikigPageAbbrev(String searchType) {
481 		if (searchType == null) {
482 			return null;
483 		}
484 		if (searchType.equals("enumeration.management.search")) {
485 			return "EM";
486 		}
487 		if (searchType.startsWith("lu.")) {
488 			return "LU";
489 		}
490 		if (searchType.startsWith("cluset.")) {
491 			return "LU";
492 		}
493 		if (searchType.startsWith("lo.")) {
494 			return "LO";
495 		}
496 		if (searchType.startsWith("lrc.")) {
497 			return "LRC";
498 		}
499 		if (searchType.startsWith("comment.")) {
500 			return "Comment";
501 		}
502 		if (searchType.startsWith("org.")) {
503 			return "Organization";
504 		}
505 		if (searchType.startsWith("atp.")) {
506 			return "ATP";
507 		}
508 		if (searchType.startsWith("person.")) {
509 			return "Person";
510 		}
511 		if (searchType.startsWith("proposal.")) {
512 			return "Proposal";
513 		}
514 		if (searchType.startsWith("subjectCode.")) {
515 			return "SC";
516 		}
517 		throw new IllegalArgumentException("Unknown type of search: "
518 				+ searchType);
519 	}
520 
521 	private List<LookupParamMetadata> filterConfiguredParams(
522 			List<LookupParamMetadata> params) {
523 		List<LookupParamMetadata> list = new ArrayList<LookupParamMetadata>();
524 		if (params == null) {
525 			return list;
526 		}
527 		if (params.size() == 0) {
528 			return list;
529 		}
530 		for (LookupParamMetadata param : params) {
531 			if (param.getDefaultValueString() != null) {
532 				list.add(param);
533 				continue;
534 			}
535 			if (param.getDefaultValueList() != null) {
536 				list.add(param);
537     continue;
538 			}
539 		}
540 		return list;
541 	}
542 
543  	private List<LookupParamMetadata> filterUserEnterableParams (
544 			List<LookupParamMetadata> params) {
545 		List<LookupParamMetadata> list = new ArrayList<LookupParamMetadata>();
546 		if (params == null) {
547 			return list;
548 		}
549 		if (params.size() == 0) {
550 			return list;
551 		}
552 		for (LookupParamMetadata param : params) {
553 			if (param.getWriteAccess () != null) {
554     if ( ! param.getWriteAccess ().equals (Metadata.WriteAccess.NEVER)) {
555 			 	list.add(param);
556 			 	continue;
557     }
558 			}
559 		}
560 		return list;
561 	}
562 
563 	private String calcRepeating(Metadata fieldMeta) {
564 		if (!fieldMeta.getDataType().equals(Data.DataType.LIST)) {
565 			return " ";
566 		}
567 		// return "repeating";
568 		MetadataInterrogator mi = new MetadataInterrogator(fieldMeta);
569 		if (mi.getSmallestMaxOccurs() == null) {
570 			if (mi.getLargestMinOccurs() != null
571 					&& mi.getLargestMinOccurs() > 1) {
572 				return "repeating: minimum " + mi.getLargestMinOccurs()
573 						+ " times";
574 			}
575 			return "repeating: unlimited";
576 		}
577 		if (mi.getSmallestMaxOccurs() == 0) {
578 			return "NOT USED";
579 		}
580 		if (mi.getSmallestMaxOccurs() == 1) {
581 			return " ";
582 			// return "single";
583 		}
584 
585 		if (mi.getLargestMinOccurs() != null) {
586 			if (mi.getLargestMinOccurs() > 1) {
587 				return "repeating: " + mi.getLargestMinOccurs() + " to "
588 						+ mi.getSmallestMaxOccurs() + " times";
589 			}
590 		}
591 		return "repeating: maximum " + mi.getSmallestMaxOccurs() + " times";
592 	}
593 
594 	private String calcLength(Metadata fieldMeta) {
595 		MetadataInterrogator mi = new MetadataInterrogator(fieldMeta);
596 		if (mi.getSmallestMaxLength() != null) {
597 			if (mi.getLargestMinLength() != null
598 					&& mi.getLargestMinLength() != 0) {
599 				if (mi.getSmallestMaxLength() == mi.getLargestMinLength()) {
600 					return ("(must be " + mi.getSmallestMaxLength() + ")");
601 				}
602 				return "(" + mi.getLargestMinLength() + " to "
603 						+ mi.getSmallestMaxLength() + ")";
604 			}
605 			return "(up to " + mi.getSmallestMaxLength() + ")";
606 		}
607 		if (mi.getLargestMinLength() != null) {
608 			return "(over " + mi.getLargestMinLength() + ")";
609 		}
610 		return " ";
611 	}
612 }