View Javadoc
1   /**
2    * Copyright 2004-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.student.contract.model.util;
17  
18  import org.kuali.student.contract.exception.DictionaryExecutionException;
19  import org.kuali.student.contract.model.*;
20  
21  import java.util.ArrayList;
22  import java.util.LinkedHashSet;
23  import java.util.List;
24  import java.util.Set;
25  
26  /**
27   * Utility that implements searches of the spreadsheet model that are needed
28   * TODO: refactor all the *Writer to use this instead of their own finds.
29   * @author nwright
30   */
31  public class ModelFinder {
32  
33      private SearchModel searchModel;
34      private ServiceContractModel serviceContractModel;
35      private DictionaryModel dictionaryModel;
36  
37      public ModelFinder(DictionaryModel model) {
38          this.dictionaryModel = model;
39          this.searchModel = model;
40          this.serviceContractModel = model;
41      }
42  
43      public ModelFinder(SearchModel model) {
44          this.searchModel = model;
45      }
46  
47      public ModelFinder(ServiceContractModel model) {
48          this.serviceContractModel = model;
49      }
50  
51      public XmlType findXmlType(String xmlTypeName) {
52          for (XmlType xmlType : serviceContractModel.getXmlTypes()) {
53              if (xmlTypeName.equalsIgnoreCase(xmlType.getName())) {
54                  return xmlType;
55              }
56          }
57          return null;
58      }
59  
60      public List<State> findStates(String xmlObject) {
61          List<State> list = new ArrayList();
62          for (State state : dictionaryModel.getStates()) {
63              if (state.getXmlObject().equalsIgnoreCase(xmlObject)) {
64                  list.add(state);
65              }
66          }
67          return list;
68      }
69  
70      public List<Type> findTypes(String xmlObject) {
71          List<Type> list = new ArrayList();
72          for (Type type : dictionaryModel.getTypes()) {
73              if (type.getXmlObject().equalsIgnoreCase(xmlObject)) {
74                  list.add(type);
75              }
76          }
77          return list;
78      }
79  
80      public Type findType(String xmlObject, String typeName) {
81          if (typeName.equalsIgnoreCase(State.DEFAULT)) {
82              return this.getDefaultType();
83          }
84          for (Type type : dictionaryModel.getTypes()) {
85              if (type.getXmlObject().equalsIgnoreCase(xmlObject)) {
86                  if (type.getName().equalsIgnoreCase(typeName)) {
87                      return type;
88                  }
89              }
90          }
91          return null;
92      }
93  
94      public Type findType(String typeKey) {
95          for (Type type : dictionaryModel.getTypes()) {
96              if (type.getTypeKey().equalsIgnoreCase(typeKey)) {
97                  return type;
98              }
99          }
100         return null;
101     }
102 
103     public State findState(String xmlObject, String stateName) {
104         if (stateName.equalsIgnoreCase(State.DEFAULT)) {
105             return this.getDefaultState();
106         }
107         for (State state : dictionaryModel.getStates()) {
108             if (state.getXmlObject().equalsIgnoreCase(xmlObject)) {
109                 if (state.getName().equalsIgnoreCase(stateName)) {
110                     return state;
111                 }
112             }
113         }
114         return null;
115     }
116 
117     public State findState(String stateKey) {
118         for (State state : dictionaryModel.getStates()) {
119             if (state.getStateKey().equalsIgnoreCase(stateKey)) {
120                 return state;
121             }
122         }
123         return null;
124     }
125 
126     public Dictionary findRoot(Dictionary dict) {
127         if (dict.getParent() == null) {
128             return dict;
129         }
130         return findRoot(dict.getParent());
131     }
132 
133     /**
134      * get dictionary entry for the id
135      * @return
136      */
137     public Dictionary findDictionaryEntry(String dictId) {
138         for (Dictionary d : dictionaryModel.getDictionary()) {
139             if (d.getId().equalsIgnoreCase(dictId)) {
140                 return d;
141             }
142         }
143         return null;
144     }
145 
146     /**
147      * get dictionary entries for the state overries
148      * @return
149      */
150     public List<Dictionary> findChildDictionaryEntries(Dictionary parent) {
151         List<Dictionary> list = new ArrayList();
152         for (Dictionary d : dictionaryModel.getDictionary()) {
153             if (d.getParent() == null) {
154                 continue;
155             }
156             if (d.getParent().equals(parent)) {
157                 list.add(d);
158             }
159         }
160         return list;
161     }
162 
163     /**
164      * get dictionary entries for the state overries
165      * @return
166      */
167     public List<Dictionary> findDefaultDictionary() {
168         List<Dictionary> list = new ArrayList(dictionaryModel.getDictionary().size());
169         for (Dictionary d : dictionaryModel.getDictionary()) {
170             if (d.getState().equalsIgnoreCase(State.DEFAULT)) {
171                 list.add(d);
172             }
173         }
174         return list;
175     }
176 
177     public List<Dictionary> findDictionaryEntriees(String xmlTypeName) {
178         List<Dictionary> list = new ArrayList();
179         for (Dictionary dict : dictionaryModel.getDictionary()) {
180             if (dict.getXmlObject().equalsIgnoreCase(xmlTypeName)) {
181                 list.add(dict);
182             }
183         }
184         return list;
185     }
186 
187     public List<Dictionary> findDefaultDictionaryEntriees(String xmlTypeName) {
188         List<Dictionary> list = new ArrayList();
189         for (Dictionary dict : this.findDefaultDictionary()) {
190             if (dict.getXmlObject().equalsIgnoreCase(xmlTypeName)) {
191                 list.add(dict);
192             }
193         }
194         return list;
195     }
196 
197     /**
198      * get dictionary entries for the state overries
199      * @return
200      */
201     public List<Dictionary> findStateOverrideDictionary() {
202         List<Dictionary> list = new ArrayList(dictionaryModel.getDictionary().size());
203         for (Dictionary d : dictionaryModel.getDictionary()) {
204             if (!d.getState().equalsIgnoreCase(State.DEFAULT)) {
205                 list.add(d);
206             }
207         }
208         return list;
209     }
210 
211     /**
212      * Expands a type that has a status of Type.GROUPING.
213      * A group can contain another group
214      * @param state
215      * @return
216      */
217     public Set<Type> expandType(Type type) {
218         Set<Type> types = new LinkedHashSet();
219         if (!type.getStatus().equalsIgnoreCase(Type.GROUPING)) {
220             types.add(type);
221             return types;
222         }
223         String pattern = type.getTypeKey();
224         GroupTypeStatePatternMatcher matcher =
225                 new GroupTypeStatePatternMatcher(pattern);
226         for (Type t : dictionaryModel.getTypes()) {
227             // can't match yourself
228             if (t == type) {
229                 //System.out.println ("skipping itself " + type.getName ());
230                 continue;
231             }
232             if (!t.getInclude()) {
233                 continue;
234             }
235 
236             // must match the same type of object
237             if (type.getXmlObject().equalsIgnoreCase(t.getXmlObject())) {
238                 if (matcher.matches(t.getTypeKey())) {
239                     if (t.getStatus().equalsIgnoreCase(Type.GROUPING)) {
240                         //TODO: Worry about self-recursion
241                         types.addAll(expandType(t));
242                     } else {
243                         types.add(t);
244                     }
245                 }
246             }
247         }
248         return types;
249     }
250 
251     /**
252      * Expands a type that has a status of Type.GROUPING.
253      * A group can contain another group
254      * @param state
255      * @return
256      */
257     public Set<State> expandState(State state) {
258         Set<State> states = new LinkedHashSet();
259         if (!state.getStatus().equalsIgnoreCase(State.GROUPING)) {
260             states.add(state);
261             return states;
262         }
263         String pattern = state.getStateKey();
264         GroupTypeStatePatternMatcher matcher =
265                 new GroupTypeStatePatternMatcher(pattern);
266         for (State s : dictionaryModel.getStates()) {
267             // can't match yourself
268             if (s == state) {
269                 //System.out.println ("skipping itself " + state.getName ());
270                 continue;
271             }
272             if (!s.getInclude()) {
273                 continue;
274             }
275 
276             // must match the same type of object
277             if (state.getXmlObject().equalsIgnoreCase(s.getXmlObject())) {
278                 if (matcher.matches(s.getStateKey())) {
279                     if (s.getStatus().equalsIgnoreCase(Type.GROUPING)) {
280                         //TODO: Worry about self-recursion
281                         states.addAll(expandState(s));
282                     } else {
283                         states.add(s);
284                     }
285                 }
286             }
287         }
288         return states;
289     }
290 
291     public Constraint findConstraint(String id) {
292         for (Constraint cons : dictionaryModel.getConstraints()) {
293             if (cons.getId().equalsIgnoreCase(id)) {
294                 return cons;
295             }
296         }
297         return null;
298     }
299 
300     private static String stripListFromType(String type) {
301         if (type.endsWith("List")) {
302             return type.substring(0, type.length() - "List".length());
303         }
304         return type;
305     }
306 
307     private void loadAllComplexSubTypes(Set<XmlType> types, String xmlTypeName) {
308         for (MessageStructure ms : this.findMessageStructures(xmlTypeName)) {
309             XmlType type = this.findXmlType(stripListFromType(ms.getType()));
310             if (type != null) {
311                 if (type.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
312                     if (types.add(type)) {
313 //                        System.out.println("debug: " + xmlTypeName + "." + ms.getShortName() + " " + type.getName());
314                         loadAllComplexSubTypes(types, type.getName());
315                     }
316                 }
317             }
318         }
319     }
320 
321     public Set<XmlType> findAllComplexSubTypes(String xmlTypeName) {
322         Set<XmlType> types = new LinkedHashSet();
323         this.loadAllComplexSubTypes(types, xmlTypeName);
324         return types;
325     }
326 
327     public Set<XmlType> findAllComplexTypesInService(String service) {
328         Set<XmlType> allTypes = findMainXmlTypesInService(service);
329         for (XmlType type : findMainXmlTypesInService(service)) {
330             this.loadAllComplexSubTypes(allTypes, type.getName());
331         }
332         return allTypes;
333     }
334 
335     public Set<XmlType> findMainXmlTypesInService(String service) {
336         Set<XmlType> types = new LinkedHashSet();
337         for (ServiceMethod method : this.findServiceMethods(service)) {
338             XmlType type = this.findXmlType(stripListFromType(method.getReturnValue().getType()));
339             if (type != null) {
340                 if (type.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
341                     types.add(type);
342                 }
343             }
344 
345             for (ServiceMethodParameter param : method.getParameters()) {
346                 type = this.findXmlType(stripListFromType(param.getType()));
347                 if (type != null) {
348                     if (type.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
349                         types.add(type);
350                     }
351                 }
352                 break;
353             }
354         }
355         return types;
356     }
357 
358     public Field findField(String id) {
359         for (Field field : dictionaryModel.getFields()) {
360             if (field.getId().equalsIgnoreCase(id)) {
361                 return field;
362             }
363         }
364         return null;
365     }
366 
367     public Field findField(String xmlTypeName, String shortName) {
368         return findField(xmlTypeName + "." + shortName);
369     }
370 
371     public Field findField(Dictionary dict) {
372         if (dict.isDynamic()) {
373             return findField(dict.getXmlObject(), "attributes");
374         }
375         return findField(dict.getXmlObject(), dict.getShortName());
376     }
377 
378     public List<Field> findFields(String xmlTypeName) {
379         List<Field> list = new ArrayList();
380         for (Field field : dictionaryModel.getFields()) {
381             if (field.getXmlObject().equalsIgnoreCase(xmlTypeName)) {
382                 list.add(field);
383             }
384         }
385         return list;
386     }
387 
388     public Service findService(String key) {
389         for (Service serv : serviceContractModel.getServices()) {
390             if (serv.getKey().equalsIgnoreCase(key)) {
391                 return serv;
392             }
393         }
394         return null;
395     }
396 
397     public Project findProject(String key) {
398         for (Project proj : dictionaryModel.getProjects()) {
399             if (proj.getKey().equalsIgnoreCase(key)) {
400                 return proj;
401             }
402         }
403         return null;
404     }
405 
406     public SearchType findSearchType(String key) {
407         for (SearchType st : searchModel.getSearchTypes()) {
408             if (st.getKey().equalsIgnoreCase(key)) {
409                 return st;
410             }
411         }
412         return null;
413     }
414 
415     public List<ServiceMethod> findServiceMethods(String service) {
416         List<ServiceMethod> methods = new ArrayList<ServiceMethod>();
417         for (ServiceMethod method : serviceContractModel.getServiceMethods()) {
418             if (method.getService().equalsIgnoreCase(service)) {
419                 methods.add(method);
420             }
421         }
422         return methods;
423     }
424 
425     public ServiceMethod findServiceMethod(String service, String name) {
426         for (ServiceMethod method : serviceContractModel.getServiceMethods()) {
427             if (method.getService().equalsIgnoreCase(service)) {
428                 if (method.getName().equalsIgnoreCase(name)) {
429                     return method;
430                 }
431             }
432         }
433         return null;
434     }
435 
436     public List<ServiceMethod> getServiceMethodsInService(String service) {
437         List<ServiceMethod> list = new ArrayList();
438         for (ServiceMethod method : serviceContractModel.getServiceMethods()) {
439             if (method.getService().equalsIgnoreCase(service)) {
440                 list.add(method);
441             }
442         }
443         return list;
444     }
445 
446     public List<MessageStructure> findMessageStructures(String xmlType) {
447         List<MessageStructure> list = new ArrayList();
448         for (MessageStructure ms : serviceContractModel.getMessageStructures()) {
449             if (ms.getXmlObject().equalsIgnoreCase(xmlType)) {
450                 list.add(ms);
451             }
452         }
453         return list;
454     }
455 
456     public MessageStructure findMessageStructure(String xmlType, String shortName) {
457         for (MessageStructure ms : serviceContractModel.getMessageStructures()) {
458             if (ms.getXmlObject().equalsIgnoreCase(xmlType)) {
459                 if (ms.getShortName().equalsIgnoreCase(shortName)) {
460                     return ms;
461                 }
462             }
463         }
464         return null;
465     }
466     private Type defaultType = null;
467 
468     public Type getDefaultType() {
469         if (defaultType != null) {
470             return defaultType;
471         }
472         List<Type> list = findTypes(Type.DEFAULT);
473         if (list.size() == 0) {
474             throw new DictionaryExecutionException("No default Type found");
475         }
476         if (list.size() > 1) {
477             throw new DictionaryExecutionException("More than one default Type found");
478         }
479         defaultType = list.get(0);
480         return defaultType;
481     }
482     private State defaultState = null;
483 
484     public State getDefaultState() {
485         if (defaultState != null) {
486             return defaultState;
487         }
488         List<State> list = findStates(State.DEFAULT);
489         if (list.size() == 0) {
490             throw new DictionaryExecutionException("No default State found");
491         }
492         if (list.size() > 1) {
493             throw new DictionaryExecutionException("More than one default State found");
494         }
495         defaultState = list.get(0);
496         return defaultState;
497     }
498 }