001 /** 002 * Copyright 2004-2014 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.opensource.org/licenses/ecl2.php 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 }