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