View Javadoc

1   /*
2    * Copyright 2009 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may	obtain a copy of the License at
7    *
8    * 	http://www.osedu.org/licenses/ECL-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.student.contract.model.validation;
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.HashSet;
21  import java.util.List;
22  import java.util.Set;
23  
24  import org.kuali.student.contract.model.SearchCriteria;
25  import org.kuali.student.contract.model.SearchCriteriaParameter;
26  import org.kuali.student.contract.model.SearchModel;
27  import org.kuali.student.contract.model.SearchResult;
28  import org.kuali.student.contract.model.SearchResultColumn;
29  import org.kuali.student.contract.model.SearchType;
30  import org.kuali.student.contract.model.util.ModelFinder;
31  
32  /**
33   * Validates the entire spreadsheet model
34   * @author nwright
35   */
36  public class SearchModelValidator implements ModelValidator {
37  
38      private SearchModel model;
39  
40      public SearchModelValidator(SearchModel model) {
41          this.model = model;
42      }
43      List<String> errors = new ArrayList();
44  
45      @Override
46      public Collection<String> validate() {
47          errors = new ArrayList();
48          validateSearchTypes();
49          return errors;
50      }
51  
52      private void validateSearchTypes() {
53          if (model.getSearchTypes().size() == 0) {
54              addError("No search types found");
55          }
56          validateForDuplicates();
57          for (SearchType st : model.getSearchTypes()) {
58              SearchTypeValidator stv = new SearchTypeValidator(st, model);
59              errors.addAll(stv.validate());
60          }
61          getValidateSearchCriteria(true);
62          getValidateSearchCriteriaParameters(true);
63          getValidateSearchResults(true);
64          getValidateSearchResultColumns(true);
65      }
66  
67      private void validateForDuplicates() {
68          Set<String> keys = new HashSet();
69          for (SearchType st : model.getSearchTypes()) {
70              if (!keys.add(st.getKey())) {
71                  SearchType st2 = new ModelFinder(model).findSearchType(st.getKey());
72                  List<String> differences = findDifferences(st, st2);
73                  if (differences.size() > 0) {
74                      StringBuffer buf = new StringBuffer();
75                      String comma = "";
76                      for (String val : differences) {
77                          buf.append(comma);
78                          buf.append(val);
79                          comma = ", ";
80                      }
81                      addError("Search type [" + st.getKey()
82                              + "] is duplicated but differences were found: " + buf);
83                  }
84              }
85          }
86      }
87  
88      private List<String> findDifferences(SearchType st1, SearchType st2) {
89          List<String> differences = new ArrayList();
90          addIfDifferent(differences, st1.getKey(), st2.getKey(), "key");
91          addIfDifferent(differences, st1.getName(), st2.getName(), "name");
92          addIfDifferent(differences, st1.getDescription(), st2.getDescription(), "Description");
93          addIfDifferent(differences, st1.getService(), st2.getService(), "Service");
94  
95          SearchCriteria sc1 = st1.getSearchCriteria();
96          SearchCriteria sc2 = st2.getSearchCriteria();
97          addIfDifferent(differences, sc1.getKey(), sc2.getKey(), "key");
98          addIfDifferent(differences, sc1.getName(), sc2.getName(), "name");
99          addIfDifferent(differences, sc1.getDescription(), sc2.getDescription(), "Description");
100 
101         List<SearchCriteriaParameter> scp1s = sc1.getParameters();
102         List<SearchCriteriaParameter> scp2s = sc2.getParameters();
103         addIfDifferent(differences, scp1s.size(), scp2s.size(), "# of parameters");
104 
105         if (scp1s.size() == scp2s.size()) {
106             for (int i = 0; i < scp1s.size(); i++) {
107                 SearchCriteriaParameter scp1 = scp1s.get(i);
108                 SearchCriteriaParameter scp2 = scp2s.get(i);
109                 addIfDifferent(differences, scp1.getKey(), scp2.getKey(), "key");
110                 addIfDifferent(differences, scp1.getName(), scp2.getName(), "name");
111                 addIfDifferent(differences, scp1.getDescription(), scp2.getDescription(), "Description");
112                 addIfDifferent(differences, scp1.getDataType(), scp2.getDataType(), "Datatype");
113                 addIfDifferent(differences, scp1.getOptional(), scp2.getOptional(), "Optional");
114                 addIfDifferent(differences, scp1.getCaseSensitive(), scp2.getCaseSensitive(), "case");
115             }
116         }
117 
118 
119         SearchResult sr1 = st1.getSearchResult();
120         SearchResult sr2 = st2.getSearchResult();
121         addIfDifferent(differences, sr1.getKey(), sr2.getKey(), "key");
122         addIfDifferent(differences, sr1.getName(), sr2.getName(), "name");
123         addIfDifferent(differences, sr1.getDescription(), sr2.getDescription(), "Description");
124         List<SearchResultColumn> src1s = sr1.getResultColumns();
125         List<SearchResultColumn> src2s = sr2.getResultColumns();
126         addIfDifferent(differences, src1s.size(), src2s.size(), "# of result columns");
127         if (src1s.size() == src2s.size()) {
128             for (int i = 0; i < src1s.size(); i++) {
129                 SearchResultColumn src1 = src1s.get(i);
130                 SearchResultColumn src2 = src2s.get(i);
131                 addIfDifferent(differences, src1.getKey(), src2.getKey(), "key");
132                 addIfDifferent(differences, src1.getName(), src2.getName(), "name");
133                 addIfDifferent(differences, src1.getDescription(), src2.getDescription(), "Description");
134                 addIfDifferent(differences, src1.getDataType(), src2.getDataType(), "Datatype");
135                 addIfDifferent(differences, src1.getOptional(), src2.getOptional(), "Optional");
136                 addIfDifferent(differences, src1.getCaseSensitive(), src2.getCaseSensitive(), "case");
137             }
138         }
139         return differences;
140     }
141 
142     private void addIfDifferent(List<String> differences, Object val1, Object val2,
143             String difference) {
144         if (val1 == null && val2 == null) {
145             return;
146         }
147         if (val1 == null) {
148             differences.add(difference);
149             return;
150         }
151         if (!val1.equals(val2)) {
152             differences.add(difference);
153         }
154     }
155 
156     private List<SearchResult> getValidateSearchResults(boolean validate) {
157         List<SearchResult> list = new ArrayList();
158         Set<String> keys = new HashSet();
159         for (SearchType st : model.getSearchTypes()) {
160             if (keys.add(st.getSearchResult().getKey())) {
161                 list.add(st.getSearchResult());
162             } else {
163                 if (validate) {
164                     for (SearchResult result : list) {
165                         if (result.getKey().equals(st.getSearchResult().getKey())) {
166                             compareSearchResults(result, st.getSearchResult());
167                         }
168                     }
169                 }
170             }
171         }
172         return list;
173     }
174 
175     private void compareSearchResults(SearchResult result1, SearchResult result2) {
176         assert result1.getKey().equals(result2.getKey());
177         if (!result1.getName().equals(result2.getName())) {
178             addError("two results with the same key have different names, one is on row "
179                     + result1.getRowNumber() + " the other is on row " + result2.getRowNumber());
180         }
181         if (!result1.getDescription().equals(result2.getDescription())) {
182             addError("Two results with the same key have different descriptions, one is on row "
183                     + result1.getRowNumber() + " the other is on row " + result2.getRowNumber());
184         }
185         if (result1.getResultColumns().size() != result2.getResultColumns().size()) {
186             addError("two results with the same key have different number of result columns, one is on row "
187                     + result1.getRowNumber() + " the other is on row " + result2.getRowNumber());
188         }
189         int i = 0;
190         for (SearchResultColumn col : result1.getResultColumns()) {
191             if (!col.getKey().equals(result2.getResultColumns().get(i).getKey())) {
192                 addError("two results with the same key have different result columns, one is on row "
193                         + result1.getRowNumber() + " the other is on row " + result2.getRowNumber()
194                         + " the result columns that are different are on row " + col.getRowNumber());
195             }
196             i++;
197         }
198     }
199 
200     private List<SearchResultColumn> getValidateSearchResultColumns(
201             boolean validate) {
202         List<SearchResultColumn> list = new ArrayList();
203         Set<String> keys = new HashSet();
204         for (SearchResult searchResult : getValidateSearchResults(false)) {
205             for (SearchResultColumn col : searchResult.getResultColumns()) {
206                 if (keys.add(col.getKey())) {
207                     list.add(col);
208                 } else {
209                     if (validate) {
210                         for (SearchResultColumn resultCol : list) {
211                             if (resultCol.getKey().equals(col.getKey())) {
212                                 compareSearchResultColumns(resultCol, col);
213                             }
214                         }
215                     }
216                 }
217             }
218         }
219         return list;
220     }
221 
222     private void compareSearchResultColumns(SearchResultColumn col1,
223             SearchResultColumn col2) {
224         assert col1.getKey().equals(col2.getKey());
225         if (!col1.getName().equals(col2.getName())) {
226             addError("two result columns with the same key have different names, one is on row "
227                     + col1.getRowNumber() + " the other is on row "
228                     + col2.getRowNumber());
229         }
230         if (!col1.getDescription().equals(col2.getDescription())) {
231             addError("Two result columns with the same key have different descriptions, one is on row "
232                     + col1.getRowNumber() + " the other is on row "
233                     + col2.getRowNumber());
234         }
235         if (!col1.getDataType().equals(col2.getDataType())) {
236             addError("Two result columns with the same key have different data type, one is on row "
237                     + col1.getRowNumber() + " the other is on row "
238                     + col2.getRowNumber());
239         }
240     }
241 
242     private List<SearchCriteria> getValidateSearchCriteria(boolean validate) {
243         List<SearchCriteria> list = new ArrayList();
244         Set<String> keys = new HashSet();
245         for (SearchType st : model.getSearchTypes()) {
246             if (keys.add(st.getSearchCriteria().getKey())) {
247                 list.add(st.getSearchCriteria());
248             } else {
249                 if (validate) {
250                     for (SearchCriteria criteria : list) {
251                         if (criteria.getKey().equals(st.getSearchCriteria().getKey())) {
252                             compareSearchCriteria(criteria, st.getSearchCriteria());
253                         }
254                     }
255                 }
256             }
257         }
258         return list;
259     }
260 
261     private void compareSearchCriteria(SearchCriteria criteria1,
262             SearchCriteria criteria2) {
263         assert criteria1.getKey().equals(criteria2.getKey());
264         if (!criteria1.getName().equals(criteria2.getName())) {
265             addError("two criteria with the same key have different names, one is on row "
266                     + criteria1.getRowNumber() + " the other is on row "
267                     + criteria2.getRowNumber());
268         }
269         if (!criteria1.getDescription().equals(criteria2.getDescription())) {
270             addError("Two criteria with the same key have different descriptions, one is on row "
271                     + criteria1.getRowNumber() + " the other is on row "
272                     + criteria2.getRowNumber());
273         }
274         if (criteria1.getParameters().size() != criteria2.getParameters().size()) {
275             addError("two results with the same key have different number of result columns, one is on row "
276                     + criteria1.getRowNumber() + " the other is on row "
277                     + criteria2.getRowNumber());
278         }
279         int i = 0;
280         for (SearchCriteriaParameter param : criteria1.getParameters()) {
281             if (!param.getKey().equals(criteria2.getParameters().get(i).getKey())) {
282                 addError("two criteria with the same key have different parameters, one is on row "
283                         + criteria1.getRowNumber() + " the other is on row " + criteria2.getRowNumber()
284                         + " the parameters that are different are on row " + param.getRowNumber());
285             }
286             i++;
287         }
288     }
289 
290     private List<SearchCriteriaParameter> getValidateSearchCriteriaParameters(
291             boolean validate) {
292         List<SearchCriteriaParameter> list = new ArrayList();
293         Set<String> keys = new HashSet();
294         for (SearchCriteria criteria : getValidateSearchCriteria(false)) {
295             for (SearchCriteriaParameter parm : criteria.getParameters()) {
296                 if (keys.add(parm.getKey())) {
297                     list.add(parm);
298                 } else {
299                     if (validate) {
300                         for (SearchCriteriaParameter param : list) {
301                             if (param.getKey().equals(parm.getKey())) {
302                                 compareSearchCriteriaParameter(param, parm);
303                             }
304                         }
305                     }
306                 }
307             }
308         }
309         return list;
310     }
311 
312     private void compareSearchCriteriaParameter(SearchCriteriaParameter param1,
313             SearchCriteriaParameter param2) {
314         assert param1.getKey().equals(param2.getKey());
315         if (!param1.getName().equals(param2.getName())) {
316             addError("two criteria parameters with the same key have different names, one is on row "
317                     + param1.getRowNumber() + " the other is on row "
318                     + param2.getRowNumber());
319         }
320         if (!param1.getDescription().equals(param2.getDescription())) {
321             addError("Two criteria parameters with the same key have different descriptions, one is on row "
322                     + param1.getRowNumber() + " the other is on row "
323                     + param2.getRowNumber());
324         }
325         if (!param1.getDataType().equals(param2.getDataType())) {
326             addError("Two criteria parameters with the same key have different data type, one is on row "
327                     + param1.getRowNumber() + " the other is on row "
328                     + param2.getRowNumber());
329         }
330     }
331 
332     private void addError(String msg) {
333         String error = "Error in overall spreadsheet: " + msg;
334         if (!errors.contains(error)) {
335             errors.add(error);
336         }
337     }
338 }