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 /*
017 * To change this template, choose Tools | Templates
018 * and open the template in the editor.
019 */
020 package org.kuali.student.contract.model.util;
021
022 import java.util.List;
023
024 import org.kuali.student.contract.exception.DictionaryExecutionException;
025 import org.kuali.student.contract.model.Dictionary;
026 import org.kuali.student.contract.model.DictionaryModel;
027 import org.kuali.student.contract.model.Field;
028 import org.kuali.student.contract.model.XmlType;
029
030 /**
031 *
032 * @author nwright
033 */
034 public class DictionaryParentSetter {
035
036 private DictionaryModel model;
037 private ModelFinder finder;
038
039 public DictionaryParentSetter(DictionaryModel model) {
040 this.model = model;
041 this.finder = new ModelFinder(model);
042 }
043
044 public void set() {
045 for (int i = 1; i < model.getDictionary().size(); i++) {
046 Dictionary child = model.getDictionary().get(i);
047 Dictionary parent = calcParent(i, child);
048 child.setParent(parent);
049 }
050 }
051
052 private Dictionary calcParent(int index, Dictionary child) {
053 // if first field the parent is by default null
054 // course.official
055 if (index == 0) {
056 return null;
057 }
058 // if first field of the defnition of a new main type
059 // then the parent is null
060 // i.e. program.official is the start of a new cluInfo definition
061 XmlType xmlType = finder.findXmlType(child.getXmlObject());
062 if (xmlType == null) {
063 throw new DictionaryExecutionException("child.getXmlObject ()=" + child.getXmlObject());
064 }
065 if (xmlType.hasOwnCreateUpdate()) {
066 List<Field> fields = finder.findFields(child.getXmlObject());
067 if (fields.get(0).getShortName().equalsIgnoreCase(child.getShortName())) {
068 return null;
069 }
070 }
071 Dictionary prev = model.getDictionary().get(index - 1);
072 // if this is just another field on same object as prev
073 // then they have the same parent
074 // course.official.no cluIdentifierInfo
075 // course.official.transcriptTitle cluIdentifierInfo << this has the same parent as previous
076 if (prev.getXmlObject().equalsIgnoreCase(child.getXmlObject())) {
077 return prev.getParent();
078 }
079 // objects are different so check if we are going down or up
080 // if going down the hierarchy
081 Field prevField = finder.findField(prev);
082 if (prevField == null) {
083 throw new DictionaryExecutionException("Could not find field associated with dictionary entry with id =" + prev.getId());
084 }
085 // going down heirarchy if this sub-object is the same type of the previous field
086 // because that means this field is the 1st field of the sub-type definition
087 if (calcType(prevField.getXmlType()).equalsIgnoreCase(child.getXmlObject())) {
088 // loop back to find the first (default) definition for that field -- that is the real parent
089 // not the state override
090 // course.desc <<<< Make this the parent
091 // course.desc.draft.private
092 // course.desc.template
093 // course.desc.draft.public <<<< not this
094 // course.desc.plain <<<< of this
095 for (int i = index - 2; i > -1; i--) {
096 Dictionary prev2 = model.getDictionary().get(i);
097 if (prev2.getXmlObject().equalsIgnoreCase(prev.getXmlObject())) {
098 if (prev2.getShortName().equalsIgnoreCase(prev.getShortName())) {
099 prev = prev2;
100 continue;
101 }
102 }
103 break;
104 }
105 return prev;
106 }
107 // we are popping up from down in the heirarchy
108 // have to go back to find the previous item at the same level
109 // course.desc cluInfo
110 // course.desc.draft.private cluInfo
111 // course.desc.template cluInfo
112 // course.desc.draft.public cluInfo << use this parent
113 // course.desc.plain richTextInfo
114 // course.desc.plain.draft.private richTextInfo
115 // course.desc.plain.draft.public richTextInfo
116 // course.desc.formatted richTextInfo
117 // course.desc.formatted.draft.private richTextInfo
118 // course.desc.formatted.draft.public richTextInfo
119 // course.rationale cluInfo << as this field's parent
120 for (int i = index - 1; i > -1; i--) {
121 Dictionary dict = model.getDictionary().get(i);
122 if (dict.getXmlObject().equalsIgnoreCase(child.getXmlObject())) {
123 return dict.getParent();
124 }
125 }
126 throw new DictionaryExecutionException("dictionary entry " + child.getId()
127 + " could not calculate the parent");
128 }
129
130 private String calcType(String type) {
131 if (type.endsWith("List")) {
132 type = type.substring(0, type.length() - "List".length());
133 }
134
135 return type;
136 }
137 }