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 */
016package org.kuali.student.datadictionary.util;
017
018import java.util.ArrayList;
019import java.util.Arrays;
020import java.util.List;
021import java.util.Stack;
022import org.kuali.rice.krad.datadictionary.AttributeDefinition;
023import org.kuali.rice.krad.datadictionary.ComplexAttributeDefinition;
024import org.kuali.rice.krad.datadictionary.DataDictionaryDefinitionBase;
025import org.kuali.rice.krad.datadictionary.DataObjectEntry;
026
027public class Dictionary2BeanComparer {
028
029    private String className;
030    private DataObjectEntry osDict;
031
032    public Dictionary2BeanComparer(String className, DataObjectEntry osDict) {
033        this.className = className;
034        this.osDict = osDict;
035    }
036
037    public List<String> compare() {
038        if (className == null) {
039            return Arrays.asList(osDict.getFullClassName() + " does not have a corresponding java class");
040        }
041        Class<?> clazz = null;
042        try {
043            clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
044            // had to change the standard Class.forName below to the above so it uses the right class loader
045            // that is defined in KSDictionaryDocMojo.java
046//            clazz = Class.forName(className);
047        } catch (ClassNotFoundException ex) {
048            return Arrays.asList("Cannot compare the dictionary entry to it's object because the object's class cannot be found");
049        }
050        Stack<DataDictionaryDefinitionBase> parentFields = new Stack<DataDictionaryDefinitionBase>();
051        Stack<Class<?>> parentClasses = new Stack<Class<?>>();
052        DataObjectEntry osBean = new Bean2DictionaryConverter(clazz, parentFields, parentClasses).convert();
053        return compare(osDict, osBean);
054
055    }
056
057    private List<String> compare(DataObjectEntry osDict,
058            DataObjectEntry osBean) {
059        List<String> discrepancies = new ArrayList();
060        compareAddDiscrepancy(discrepancies, "Java class name", osDict.getFullClassName(), osBean.getFullClassName());
061        compareAddDiscrepancy(discrepancies, "Entry class", osDict.getEntryClass(), osBean.getEntryClass());
062        for (AttributeDefinition adDict : osDict.getAttributes()) {
063            AttributeDefinition adBean = findAttributeDefinition(adDict.getName(), osBean);
064            if (adBean == null) {
065//                if (!adDict.isDynamic()) {
066                discrepancies.add("Field " + adDict.getName() + " does not exist in the corresponding java class");
067//                }
068                continue;
069            }
070            compareAddDiscrepancy(discrepancies, adDict.getName() + " dataType", adDict.getDataType(), adBean.getDataType());
071            // TODO: deal with collections
072//            compareAddDiscrepancy(discrepancies, adDict.getName() + " maxOccurs", adDict.getMaximumNumberOfElements(), adBean.getMaximumNumberOfElements());
073        }
074        for (ComplexAttributeDefinition cadDict : osDict.getComplexAttributes()) {
075            ComplexAttributeDefinition cadBean = findComplexAttributeDefinition(cadDict.getName(), osBean);
076            if (cadBean == null) {
077//                if (!adDict.isDynamic()) {
078                discrepancies.add("Field " + cadDict.getName() + " does not exist in the corresponding java class");
079//                }
080                continue;
081            }
082             // TODO: deal with collections
083//            compareAddDiscrepancy(discrepancies, adDict.getName() + " maxOccurs", adDict.getMaximumNumberOfElements(), adBean.getMaximumNumberOfElements());
084        }
085        for (AttributeDefinition fdBean : osBean.getAttributes()) {
086            AttributeDefinition fdDict = findAttributeDefinition(fdBean.getName(), osDict);
087            if (fdDict == null) {
088                discrepancies.add("Field " + fdBean.getName() + " missing from the dictictionary");
089                continue;
090            }
091        }
092        for (ComplexAttributeDefinition fdBean : osBean.getComplexAttributes()) {
093            ComplexAttributeDefinition fdDict = findComplexAttributeDefinition(fdBean.getName(), osDict);
094            if (fdDict == null) {
095                discrepancies.add("Field " + fdBean.getName() + " missing from the dictictionary");
096                continue;
097            }
098        }
099        return discrepancies;
100    }
101
102    private AttributeDefinition findAttributeDefinition(String name, DataObjectEntry ode) {
103        for (AttributeDefinition fd : ode.getAttributes()) {
104            if (name.equals(fd.getName())) {
105                return fd;
106            }
107        }
108        return null;
109    }
110
111    private ComplexAttributeDefinition findComplexAttributeDefinition(String name, DataObjectEntry ode) {
112        for (ComplexAttributeDefinition cad : ode.getComplexAttributes()) {
113            if (name.equals(cad.getName())) {
114                return cad;
115            }
116        }
117        return null;
118    }
119
120    private void compareAddDiscrepancy(List<String> discrepancies, String field, boolean value1,
121            boolean value2) {
122        String discrep = compare(field, value1, value2);
123        if (discrep != null) {
124            discrepancies.add(discrep);
125        }
126    }
127
128    private void compareAddDiscrepancy(List<String> discrepancies, String field, Object value1,
129            Object value2) {
130        String discrep = compare(field, value1, value2);
131        if (discrep != null) {
132            discrepancies.add(discrep);
133        }
134    }
135
136    private String compare(String field, boolean value1, boolean value2) {
137        if (value1) {
138            if (value2) {
139                return null;
140            }
141        }
142        if (!value1) {
143            if (!value2) {
144                return null;
145            }
146        }
147        return field + " inconsistent: dictionary='" + value1 + "', java class='" + value2 + "'";
148    }
149
150    private String compare(String field, Object value1, Object value2) {
151        if (value1 == null) {
152            if (value2 == null) {
153                return null;
154            }
155        } else {
156            if (value1.equals(value2)) {
157                return null;
158            }
159        }
160        return field + " inconsistent: dictionary='" + value1 + "'], java class='" + value2 + "'";
161    }
162}