001 /*
002 * Copyright 2009 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.osedu.org/licenses/ECL-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.student.contract.model.util;
017
018 import org.kuali.student.contract.exception.DictionaryExecutionException;
019 import org.kuali.student.contract.model.*;
020
021 import java.util.ArrayList;
022 import java.util.LinkedHashSet;
023 import java.util.List;
024 import java.util.Set;
025
026 /**
027 * Utility that implements searches of the spreadsheet model that are needed
028 * TODO: refactor all the *Writer to use this instead of their own finds.
029 * @author nwright
030 */
031 public class ModelFinder {
032
033 private SearchModel searchModel;
034 private ServiceContractModel serviceContractModel;
035 private DictionaryModel dictionaryModel;
036
037 public ModelFinder(DictionaryModel model) {
038 this.dictionaryModel = model;
039 this.searchModel = model;
040 this.serviceContractModel = model;
041 }
042
043 public ModelFinder(SearchModel model) {
044 this.searchModel = model;
045 }
046
047 public ModelFinder(ServiceContractModel model) {
048 this.serviceContractModel = model;
049 }
050
051 public XmlType findXmlType(String xmlTypeName) {
052 for (XmlType xmlType : serviceContractModel.getXmlTypes()) {
053 if (xmlTypeName.equalsIgnoreCase(xmlType.getName())) {
054 return xmlType;
055 }
056 }
057 return null;
058 }
059
060 public List<State> findStates(String xmlObject) {
061 List<State> list = new ArrayList();
062 for (State state : dictionaryModel.getStates()) {
063 if (state.getXmlObject().equalsIgnoreCase(xmlObject)) {
064 list.add(state);
065 }
066 }
067 return list;
068 }
069
070 public List<Type> findTypes(String xmlObject) {
071 List<Type> list = new ArrayList();
072 for (Type type : dictionaryModel.getTypes()) {
073 if (type.getXmlObject().equalsIgnoreCase(xmlObject)) {
074 list.add(type);
075 }
076 }
077 return list;
078 }
079
080 public Type findType(String xmlObject, String typeName) {
081 if (typeName.equalsIgnoreCase(State.DEFAULT)) {
082 return this.getDefaultType();
083 }
084 for (Type type : dictionaryModel.getTypes()) {
085 if (type.getXmlObject().equalsIgnoreCase(xmlObject)) {
086 if (type.getName().equalsIgnoreCase(typeName)) {
087 return type;
088 }
089 }
090 }
091 return null;
092 }
093
094 public Type findType(String typeKey) {
095 for (Type type : dictionaryModel.getTypes()) {
096 if (type.getTypeKey().equalsIgnoreCase(typeKey)) {
097 return type;
098 }
099 }
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 }