View Javadoc

1   /*
2    * Copyright 2011 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.impl;
17  
18  import java.io.File;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Date;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  import org.junit.After;
28  import org.junit.AfterClass;
29  import org.junit.Before;
30  import org.junit.BeforeClass;
31  import org.junit.Test;
32  import static org.junit.Assert.*;
33  
34  import org.kuali.student.contract.model.MessageStructure;
35  import org.kuali.student.contract.model.Service;
36  import org.kuali.student.contract.model.ServiceContractModel;
37  import org.kuali.student.contract.model.ServiceMethod;
38  import org.kuali.student.contract.model.ServiceMethodParameter;
39  import org.kuali.student.contract.model.XmlType;
40  import org.kuali.student.contract.model.util.HtmlContractMessageStructureWriter;
41  import org.kuali.student.contract.model.util.ModelFinder;
42  import org.kuali.student.contract.model.validation.ServiceContractModelValidator;
43  
44  /**
45   *
46   * @author nwright
47   */
48  //@Ignore
49  public class R1R2ServiceContractComparisonTest {
50  
51      public R1R2ServiceContractComparisonTest() {
52      }
53  
54      @BeforeClass
55      public static void setUpClass() throws Exception {
56      }
57  
58      @AfterClass
59      public static void tearDownClass() throws Exception {
60      }
61  
62      @Before
63      public void setUp() {
64  
65          System.out.println("This section was created by programmatically comparing the message structures.");
66          System.out.println("Run on: " + new Date());
67          System.out.println("See [R1R2ServiceContractComparisonTest.java|https://test.kuali.org/svn/student/tools/maven-kscontractdoc-plugin/trunk/src/test/java/org/kuali/student/contract/model/impl/R1R2ServiceContractComparisonTest.java]");
68          System.out.println("");
69          System.out.println("*TABLE OF CONTENTS*");
70          System.out.println("{toc}");
71          System.out.println("");
72          System.out.println("h1. Loading models of the contracts from the source code");
73          System.out.println("h2. Log from loading model for R1");
74          getModel1();
75          System.out.println("h2. Log from loading model for R2");
76          getModel2();
77          getFinder1();
78          getFinder2();
79          loadKnownObjectRenames();
80          loadKnownUnconvertedObjects();
81          loadKnownFieldRenames();
82          loadKnownFieldIssues();
83          loadKnownMethodRenames();
84          loadKnownMethodIssues ();
85      }
86  
87      @After
88      public void tearDown() {
89      }
90      private static final String RESOURCES_DIRECTORY = "src/test/resources";
91      private static final String TEST_SOURCE_DIRECTORY =
92              "src/test/java/org/kuali/student/contract/model/test/source";
93      private static final String ENROLL_PROJECT_SRC_MAIN = "C:/svn/ks-1.3-services/ks-enroll/ks-enroll-api/src/main";
94      private static final String ENROLL_PROJECT_JAVA_DIRECTORY = ENROLL_PROJECT_SRC_MAIN + "/java";
95      private static final String RICE_CORE_API_DIRECTORY = "C:/svn/rice/trunk/core/api/src/main/java";
96      private static final String RICE_KIM_API_DIRECTORY = "C:/svn/rice/trunk/kim/kim-api/src/main/java";
97      private static final String RICE_LOCATION_API_DIRECTORY = "C:/svn/rice/trunk/location/api/src/main/java";
98      private static final String RICE_KEW_API_DIRECTORY = "C:/svn/rice/trunk/kew/api/src/main/java";
99      private static final String RICE_KEN_API_DIRECTORY = "C:/svn/rice/trunk/ken/api/src/main/java";
100     private static final String RICE_KSB_API_DIRECTORY = "C:/svn/rice/trunk/ksb/api/src/main/java";
101     private static final String RICE_KRMS_API_DIRECTORY = "C:/svn/rice/trunk/krms/api/src/main/java";
102     private static final String R1_PROJECT_DIRECTORY = "C:/svn/student/";
103     private static final String CORE_API_DIRECTORY = R1_PROJECT_DIRECTORY + "ks-core/ks-core-api/src/main/java";
104     private static final String COMMON_API_DIRECTORY = R1_PROJECT_DIRECTORY + "ks-common/ks-common-api/src/main/java";
105     private static final String LUM_API_DIRECTORY = R1_PROJECT_DIRECTORY + "ks-lum/ks-lum-api/src/main/java";
106     private static ServiceContractModel model1 = null;
107     private static ServiceContractModel model2 = null;
108 
109     /**
110      * Test of getServiceMethods method, of class ServiceContractModelQDoxLoader.
111      */
112     @Test
113     public void testCompareModels() {
114         System.out.println("");
115         System.out.println("h1. Message Structure Comparison");
116         compareTypes();
117         System.out.println("");
118         System.out.println("h1. Service Method Comparison");
119         compareMethods();
120     }
121 
122     private ServiceContractModel getModel1() {
123         if (model1 != null) {
124             return model1;
125         }
126         List<String> srcDirs = new ArrayList();
127         System.out.println("User directory=" + System.getProperty("user.dir"));
128         System.out.println("Current directory=" + new File(".").getAbsolutePath());
129         srcDirs.add(COMMON_API_DIRECTORY);
130         srcDirs.add(CORE_API_DIRECTORY);
131         srcDirs.add(LUM_API_DIRECTORY);
132         System.out.println ("Reading as input:");
133         for (String directory : srcDirs) {
134             System.out.println ("* " + directory);
135         }
136         System.out.println ("");
137         boolean validateKualiStudent = false;
138         ServiceContractModel instance = new ServiceContractModelQDoxLoader(srcDirs, validateKualiStudent);
139 
140         instance = new ServiceContractModelCache(instance);
141         validate(instance);
142         model1 = instance;
143         return instance;
144     }
145 
146     private ServiceContractModel getModel2() {
147         if (model2 != null) {
148             return model2;
149         }
150         List<String> srcDirs = new ArrayList();
151         System.out.println("User directory=" + System.getProperty("user.dir"));
152         System.out.println("Current directory=" + new File(".").getAbsolutePath());
153         srcDirs.add(ENROLL_PROJECT_JAVA_DIRECTORY);
154         System.out.println ("Reading as input:");
155         for (String directory : srcDirs) {
156             System.out.println ("* " + directory);
157         }
158         System.out.println ("");     
159         boolean validateKualiStudent = true;
160         ServiceContractModel instance = new ServiceContractModelQDoxLoader(srcDirs, validateKualiStudent);
161 
162         instance = new ServiceContractModelCache(instance);
163         validate(instance);
164         model2 = instance;
165         return instance;
166     }
167 
168     private String dump(ServiceMethod method) {
169         StringBuilder bldr = new StringBuilder();
170         bldr.append(method.getName());
171         String comma = "";
172         bldr.append("(");
173         for (ServiceMethodParameter param : method.getParameters()) {
174             bldr.append(comma);
175             comma = ", ";
176             bldr.append(param.getType());
177             bldr.append(" ");
178             bldr.append(param.getName());
179         }
180         bldr.append(")");
181         return bldr.toString();
182     }
183 
184     private void validate(ServiceContractModel model) {
185         Collection<String> errors =
186                 new ServiceContractModelValidator(model).validate();
187         if (errors.size() > 0) {
188             StringBuilder buf = new StringBuilder();
189             buf.append(errors.size()).append(" errors found while validating the data.");
190             int cnt = 0;
191             for (String msg : errors) {
192                 cnt++;
193                 buf.append("\n");
194                 buf.append("*error*").append(cnt).append(":").append(msg);
195             }
196 
197             fail(buf.toString());
198         }
199     }
200     private ModelFinder finder1 = null;
201 
202     private ModelFinder getFinder1() {
203         if (finder1 == null) {
204             finder1 = new ModelFinder(getModel1());
205         }
206         return finder1;
207     }
208     private ModelFinder finder2 = null;
209 
210     private ModelFinder getFinder2() {
211         if (finder2 == null) {
212             finder2 = new ModelFinder(getModel2());
213         }
214         return finder2;
215     }
216 
217     private void compareTypes() {
218         for (Service service : model1.getServices()) {
219             System.out.println("");
220             System.out.println("h2. " + service.getName() + " Structures");
221             for (XmlType type : finder1.findAllComplexTypesInService(service.getKey())) {
222                 findCompareType(type);
223             }
224         }
225     }
226 
227     private String calcService(XmlType xmlType) {
228         StringBuilder bldr = new StringBuilder();
229         String comma = "";
230         for (String serviceKey : HtmlContractMessageStructureWriter.calcUsageByService(model1, xmlType)) {
231             bldr.append(comma);
232             comma = ", ";
233             bldr.append(serviceKey);
234         }
235         return bldr.toString();
236     }
237 
238     private String calcFieldNames(XmlType xmlType) {
239         StringBuilder bldr = new StringBuilder();
240         String comma = "";
241         for (MessageStructure ms : finder2.findMessageStructures(xmlType.getName())) {
242             bldr.append(comma);
243             comma = ", ";
244             bldr.append(ms.getShortName());
245         }
246         return bldr.toString();
247     }
248     private Map<String, String> knownUnconvertedObjects = null;
249 
250     private void loadKnownUnconvertedObjects() {
251         Map<String, String> missings = new HashMap<String, String>();
252         missings.put("ObjectStructureDefinition", "Old R1 dictionary not converted");
253         missings.put("FieldDefinition", "Old R1 dictionary not converted");
254         missings.put("ValidCharsConstraint", "Old R1 dictionary not converted");
255         missings.put("RequiredConstraint", "Old R1 dictionary not converted");
256         missings.put("CaseConstraint", "Old R1 dictionary not converted");
257         missings.put("WhenConstraint", "Old R1 dictionary not converted");
258         missings.put("Constraint", "Old R1 dictionary not converted");
259         missings.put("MustOccurConstraint", "Old R1 dictionary not converted");
260         missings.put("LookupConstraint", "Old R1 dictionary not converted");
261         missings.put("CommonLookupParam", "Old R1 dictionary not converted");
262         missings.put("CommonLookup", "Old R1 dictionary not converted");
263         missings.put("DateRangeInfo", "DateRange was merged in with Milestone");
264         missings.put("CredentialInfo", "LRC was revamped and Class II like objects were dropped");
265         missings.put("CreditInfo", "LRC was revamped and Class II like objects were dropped");
266         missings.put("ScaleInfo", "Changed to be ResultScaleInfo");
267         missings.put("GradeInfo", "LRC was revamped and Class II like objects were dropped");
268         missings.put("ResultComponentInfo", "Changed to be ResultValuesGroupInfo");
269         missings.put("QueryParamInfo", "Is really a type object that holds typing info information about a parameter model as TypeInfo and use type-type relation to connnect it to search criteria");
270         missings.put("FieldDescriptor", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
271         missings.put("SearchSelector", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
272         missings.put("ObjectStructure", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
273         missings.put("Type", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
274         missings.put("State", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
275         missings.put("Field", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
276         missings.put("ConstraintDescriptor", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
277         missings.put("ConstraintSelector", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
278         missings.put("RequireConstraint", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
279         missings.put("TypeStateCaseConstraint", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
280         missings.put("TypeStateWhenConstraint", "Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
281         missings.put("OccursConstraint", " Old pre-R1 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info");
282         missings.put("ResultColumnInfo", " is really a type that describes the type of result that comes back, store as a TypeInfo object and use type-type relation to connect to result");
283 //        missings.put("SearchCriteriaTypeInfo", "The search criteria is really a type stucture that should be modeled as as TypeInfo and type-type relationship to connect it to a search type");
284         missings.put("java.lang.String", "");
285         missings.put("Map<String, String>", "");
286         missings.put("LuiInfo", "Lui was pulled out and put in it's own service.  The LuiInfo object was not used in R1 and was radically redesigned in R2");
287 
288         knownUnconvertedObjects = missings;
289         return;
290     }
291     private Map<String, String> knownObjectRenames = null;
292 
293     private void loadKnownObjectRenames() {
294         Map<String, String> renames = new HashMap<String, String>();
295         renames.put("Message", "MessageInfo");
296         renames.put("SearchRequest", "SearchRequestInfo");
297         renames.put("SearchResult", "SearchResultInfo");
298         renames.put("SearchParam", "SearchParamInfo");
299         renames.put("SearchResultRow", "SearchResultRowInfo");
300         renames.put("SearchResultCell", "SearchResultCellInfo");
301         renames.put("Message", "MessageInfo");
302         knownObjectRenames = renames;
303         return;
304     }
305     private Map<String, String> knownFieldRenames = null;
306 
307     private void loadKnownFieldRenames() {
308         Map<String, String> renames = new HashMap<String, String>();
309         renames.put("id", "key"); // not all the time but when it happens want to catch if id not found
310         renames.put("desc", "descr");
311         renames.put("state", "stateKey");
312         renames.put("type", "typeKey");
313         renames.put("metaInfo", "meta");
314         renames.put("desc", "descr");
315         renames.put("startTerm", "startTermId");
316         renames.put("endTerm", "endTermId");
317         renames.put("longDesc", "longDescr");
318         renames.put("shortDesc", "shortDescr");
319         renames.put("objectTypeURI", "refObjectUri");
320         // TODO: this works but really should make these specific to the object they are connected with
321         renames.put("detailDesc", "descr");
322         renames.put("milestoneDate", "startDate");
323         renames.put("success", "isSuccess");
324         renames.put("relationType", "relationTypeKey");
325         renames.put("unitType", "unitTypeKey");
326         renames.put("enrollable", "isEnrollable");
327         renames.put("hazardousForDisabledStudents", "isHazardousForDisabledStudents");
328         renames.put("versionInfo", "version");
329         renames.put("primary", "isPrimary");
330         renames.put("activityType", "typeKey");
331         renames.put("loRepository", "loRepositoryKey");
332         renames.put("queryParamValueList", "queryParamValues");
333         renames.put("credentialProgramType", "typeKey");
334         knownFieldRenames = renames;
335         return;
336     }
337     private Map<String, String> knownFieldIssues = null;
338 
339     private void loadKnownFieldIssues() {
340         Map<String, String> issues = new HashMap<String, String>();
341         issues.put("AtpInfo.key", "Switched from key to Id");
342         issues.put("MilestoneInfo.key", "Switched from key to Id");
343         issues.put("AtpInfo.id", ""); // suppress the extra field message from the r2 side
344         issues.put("MilestoneInfo.id", ""); // ditto
345         issues.put("MilestoneInfo.atpId", "Is not in R2 because a Milestone can be connected to more than one ATP so it is managed through a relationship");
346         issues.put("Message.locale", "the type was changed from String to LocaleInfo to hold the different parts of the locale info");
347         issues.put("SearchRequest.params", "");
348         issues.put("SearchResult.rows", "");
349         issues.put("SearchResultRow.cells", "");
350         issues.put("ValidationResultInfo.errorLevel", "");
351         issues.put("ValidationResultInfo.level", "");
352         issues.put("ValidationResultInfo.ok", "");
353         issues.put("ValidationResultInfo.warn", "");
354         issues.put("ValidationResultInfo.error", "");
355         issues.put("DocumentInfo.documentBinaryInfo", "renamd to just documentBinary (removing the trailing Info from the field name)");
356         issues.put("OrgHierarchyInfo.key", "Switched from key to Id");
357         issues.put("SearchResultTypeInfo.resultColumns", "ResultColumns is really anotther type to describe the column, Use type-type relation to hold that info");
358         issues.put("ReqCompFieldTypeInfo.fieldDescriptor", "was dropped because it was an Old Pre-R1 dictionary and was not used -- UI dictionary provides that info instead");
359         issues.put("LuTypeInfo.instructionalFormat", "Instructional format is a TypeInfo object and should be modeled as such using the type-type relation to connect it to a learning unit type");
360         issues.put("LuTypeInfo.deliveryMethod", "Delivery method is a TypeInfo object and should be modeled as such using type-type relation to connect it to a learning unit type");
361         issues.put("SearchCriteriaTypeInfo.queryParams", "Query Params is a TypeInfo that describes the parameter, model as type and type-type relation");
362         issues.put("OrgOrgRelationTypeInfo.orgHierarchyKey", "This was removed because a particular relation type can participate in more than one hierarchies!");
363         issues.put("SearchParam.value", "Renamed to values which is List<String>, in R1 the setValue method was overloaded to take a string or List, Kept in R2 but marked as deprecated");
364         issues.put("", "");
365         issues.put("", "");
366         issues.put("", "");
367         issues.put("", "");
368         issues.put("", "");
369         issues.put("", "");
370         issues.put("", "");
371         issues.put("", "");
372         issues.put("", "");
373         issues.put("", "");
374 
375         knownFieldIssues = issues;
376         return;
377     }
378 
379     private XmlType findType(XmlType r1) {
380         XmlType r2 = finder2.findXmlType(r1.getName());
381         if (r2 == null) {
382             String renamedName = this.knownObjectRenames.get(r1.getName());
383             if (renamedName != null) {
384                 r2 = finder2.findXmlType(renamedName);
385                 if (r2 == null) {
386                     System.out.println("# (-) " + r1.getName() + ": was not found even after being renamed to " + renamedName);
387                     return null;
388                 }
389                 System.out.println("# (/) " + r1.getName() + ": was renamed to " + renamedName);
390                 return r2;
391             }
392         }
393         if (r2 == null) {
394             if (r1.getName().endsWith("TypeInfo")) {
395                 r2 = finder2.findXmlType("TypeInfo");
396             }
397         }
398         return r2;
399     }
400 
401     private void findCompareType(XmlType r1) {
402         if (r1.getName().endsWith("List")) {
403             return;
404         }
405         if (this.knownUnconvertedObjects.containsKey(r1.getName())) {
406             String message = this.knownUnconvertedObjects.get(r1.getName());
407             if (message.isEmpty()) {
408                 return;
409             }
410             System.out.println("# (/) " + r1.getName() + ":" + message);
411             return;
412         }
413         XmlType r2 = findType(r1);
414         if (r2 == null) {
415             System.out.println("# " + r1.getName() + ": has no corresponding object in r2");
416             return;
417         }
418         Set<MessageStructure> usedInR2 = new HashSet<MessageStructure>();
419         for (MessageStructure ms : finder1.findMessageStructures(r1.getName())) {
420             MessageStructure used = findCompareMessageStructure(ms, r2);
421             if (used != null) {
422                 usedInR2.add(used);
423             }
424         }
425         // Don't report extra fields on type info
426         if (!r2.getName().equals("TypeInfo")) {
427             for (MessageStructure ms : finder2.findMessageStructures(r2.getName())) {
428                 if (usedInR2.contains(ms)) {
429                     continue;
430                 }
431                 String issue = this.knownFieldIssues.get(ms.getXmlObject() + "." + ms.getShortName());
432                 if (issue != null) {
433                     if (!issue.isEmpty()) {
434                         System.out.println("# (*g) " + ms.getXmlObject() + "." + ms.getShortName() + ": " + issue);
435                     }
436                     continue;
437                 }
438                 System.out.println("# (+) " + ms.getXmlObject() + "." + ms.getShortName() + " - new field added in R2");
439             }
440         }
441     }
442 
443     private MessageStructure findCompareMessageStructure(MessageStructure r1, XmlType xmlType2) {
444         MessageStructure r2 = findMessageStructure(r1, xmlType2);
445         String issue = this.knownFieldIssues.get(r1.getXmlObject() + "." + r1.getShortName());
446         if (issue != null) {
447             if (!issue.isEmpty()) {
448                 System.out.println("# (*g) " + r1.getXmlObject() + "." + r1.getShortName() + ": " + issue);
449             }
450             return r2;
451         }
452         if (r2 == null) {
453             if (xmlType2.getName().equals("TypeInfo")) {
454                 if (r1.getShortName().endsWith("Type")
455                         || r1.getShortName().endsWith("TypeInfo")
456                         || r1.getShortName().endsWith("Types")
457                         || r1.getShortName().endsWith("TypeInfos")) {
458                     System.out.println("# (*g) " + r1.getXmlObject() + "." + r1.getShortName() + " was a type stored on a type: use type-type relationship instead");
459                     return null;
460                 }
461                 System.out.println("# (!) " + r1.getXmlObject() + "." + r1.getShortName() + " was extra data on type, store in dynamic attribute if actually used");
462                 return null;
463             }
464             System.out.println("# (-) " + r1.getXmlObject() + "." + r1.getShortName() + " not found in r2: renamed to one of these? " + calcFieldNames(xmlType2));
465             return null;
466         }
467         compareType(r1, r2);
468         return r2;
469     }
470 
471     private void compareType(MessageStructure r1, MessageStructure r2) {
472         if (r1.getType().equalsIgnoreCase(r2.getType())) {
473             return;
474         }
475         if (r1.getShortName().equals("attributes")) {
476             if (r1.getType().equals("Map<String, String>")) {
477                 if (r2.getType().equals("AttributeInfoList")) {
478                     return;
479                 }
480             }
481         }
482         if (r1.getShortName().equals("desc") || r1.getShortName().equals("descr")) {
483             if (r1.getType().equals("String")) {
484                 if (r2.getType().equals("RichTextInfo")) {
485                     System.out.println("# (*g) " + r1.getXmlObject() + "." + r1.getShortName() + ": description type were changed to RichText, use plain version");
486                     return;
487                 }
488             }
489         }
490         System.out.println("# (!) " + r1.getXmlObject() + "." + r1.getShortName() + ": the type was changed from " + r1.getType() + " to " + r2.getType());
491     }
492 
493     private MessageStructure findMessageStructure(MessageStructure r1, XmlType xmlType2) {
494         MessageStructure r2 = finder2.findMessageStructure(xmlType2.getName(), r1.getShortName());
495         if (r2 == null) {
496             String renamed = this.knownFieldRenames.get(r1.getShortName());
497             if (renamed != null) {
498                 r2 = finder2.findMessageStructure(xmlType2.getName(), renamed);
499                 if (r2 == null) {
500                     System.out.println("# (-) " + r1.getXmlObject() + "." + r1.getShortName()
501                             + " was renamed to " + xmlType2.getName() + "." + renamed
502                             + " BUT IT STILL DIDN'T EXIST IN R2");
503                     return null;
504                 }
505                 System.out.println("# (*g) " + r1.getXmlObject() + "." + r1.getShortName()
506                         + " was renamed to " + xmlType2.getName() + "." + renamed);
507             }
508         }
509         return r2;
510     }
511 
512     private void compareMethods() {
513         for (Service service : model1.getServices()) {
514             System.out.println("");
515             System.out.println("h2. " + service.getName() + " Methods");
516             List<ServiceMethod> methodsInService = finder1.findServiceMethods(service.getKey());
517             for (ServiceMethod method : methodsInService) {
518                 findCompareMethod(method);
519             }
520         }
521     }
522 
523     private void findCompareMethod(ServiceMethod method1) {
524         String issue = knownMethodIssues.get (method1.getService() + "Service." + method1.getName());
525         if (issue != null) {
526             if (!issue.isEmpty()) {
527                 System.out.println("# (*g) " + method1.getService() + "Service." + method1.getName()
528                         + ": " + issue);
529             }
530             return;
531         }
532         ServiceMethod method2 = findMethod(method1);
533         if (method2 == null) {
534 //            String possibleMethods = calcPossibleMethods(method1);
535             if (isTypeMethod(method1)) {
536                 System.out.println("# (*g) " + method1.getService() + "Service." + method1.getName()
537                         + " was dropped because it is a type, use TypeService instead");
538                 return;
539             }
540             String possibleMethods = this.calcPossibleMethods(method1);
541             if (possibleMethods.isEmpty()) {
542                 System.out.println("# (-) " + method1.getService() + "Service." + method1.getName()
543                         + " could not be found in R2");
544             } else {
545                 System.out.println("# (!) " + method1.getService() + "Service." + method1.getName()
546                         + " might have been renamed to one of these: "
547                         + possibleMethods);
548             }
549             return;
550         }
551         if (!method1.getName().equals(method2.getName())) {
552             System.out.println("# (*g) " + method1.getService() + "Service." + method1.getName()
553                     + " was renamed to " + method2.getService() + "Service." + method2.getName());
554         }
555     }
556 
557     private ServiceMethod findMethod(ServiceMethod method1) {
558         ServiceMethod method2 = findMethod2(method1.getService(), method1.getName());
559         if (method2 == null) {
560             String methodRename = knownMethodRenames.get(method1.getService() + "Service." + method1.getName());
561             if (methodRename != null) {
562                 method2 = findMethod2(method1.getService(), methodRename);
563                 if (method2 == null) {
564                     System.out.println("# (x) " + method1.getService() + "Service." + method1.getName() 
565                             + " could not be found even after being renamed to " + methodRename);
566                     return null;
567                 }
568             }
569         }
570         return method2;
571     }
572     private Map<String, String> knownMethodRenames = null;
573 
574     private void loadKnownMethodRenames() {
575         Map<String, String> renames = new HashMap<String, String>();
576         renames.put("AtpService.getAtpsByAtpType", "getAtpIdsByType");
577         renames.put("AtpService.getMilestonesByAtp", "getMilestonesForAtp");
578         renames.put("AtpService.addMilestone", "addMilestoneToAtp");
579         renames.put("AtpService.removeMilestone", "removeMilestoneFromAtp");
580         renames.put("MessageService.getMessageGroups", "getMessageGroupKeys");
581         renames.put("CommentService.getComments", "getCommentsByReferenceAndType");
582         renames.put("CommentService.getTags", "getTagsByReferenceAndType"); 
583         renames.put("CommentService.addTag", "createTag");
584         renames.put("CommentService.addComment", "createComment");
585         renames.put("CommentService.removeComment", "deleteComment");
586         renames.put("CommentService.removeTag", "deleteTag");
587         renames.put("CommentService.removeComments", "deleteCommentsByReference");
588         renames.put("CommentService.removeTags", "deleteTagsByReference");
589         renames.put("DocumentService.getDocumentsByIdList", "getDocumentsByIds");
590         renames.put("DocumentService.getCategoriesByDocument", "getDocumentCategoriesByDocumentId");
591         renames.put("DocumentService.getRefDocRelationsByDoc", "getRefDocRelationsByDocument");
592         renames.put("EnumerationManagementService.removeEnumeratedValue", "deleteEnumeratedValue");
593         renames.put("OrganizationService.getOrganization", "getOrg");
594         renames.put("OrganizationService.getOrganizationsByIdList", "getOrgsByIds");
595         renames.put("OrganizationService.getOrgOrgRelationsByIdList", "getOrgOrgRelationsByIds");
596         renames.put("OrganizationService.getOrgPersonRelationsByIdList", "getOrgPersonRelationsByIds");
597         renames.put("OrganizationService.getPersonIdsForOrgByRelationType", "");
598         renames.put("OrganizationService.getAllOrgPersonRelationsByPerson", "getOrgPersonRelationsByPerson");
599         renames.put("OrganizationService.getAllOrgPersonRelationsByOrg", "getOrgPersonRelationsByOrg");
600         renames.put("OrganizationService.createOrganization", "createOrg");
601         renames.put("OrganizationService.updateOrganization", "updateOrg");
602         renames.put("OrganizationService.deleteOrganization", "deleteOrg");
603         renames.put("OrganizationService.validateOrganization", "validateOrg");
604         renames.put("OrganizationService.removeOrgOrgRelation", "deleteOrgOrgRelation");
605         renames.put("OrganizationService.removeOrgPersonRelation", "deleteOrgPersonRelation");
606         renames.put("OrganizationService.addPositionRestrictionToOrg", "createOrgPositionRestriction");
607         renames.put("OrganizationService.updatePositionRestrictionForOrg", "updateOrgPositionRestriction");
608         renames.put("OrganizationService.removePositionRestrictionFromOrg", "deleteOrgPositionRestriction");
609         renames.put("StatementService.getStatementsUsingReqComponent", "getStatementsByReqComponent");
610         renames.put("StatementService.getStatementsUsingStatement", "getStatementsForStatement");
611         renames.put("CourseService.getCourseFormats", "getCourseFormatsByCourse");
612         renames.put("CourseService.getCourseActivities", "getCourseActivitiesByCourseFormat");
613         renames.put("CourseService.getCourseLos", "getCourseLearningObjectivesByCourse");
614         renames.put("LearningObjectiveService.getLoCategories", "getLoCategoriesByLoRepository");
615         renames.put("LearningObjectiveService.getLoByIdList", "getLosByIds");
616         renames.put("LearningObjectiveService.getLosByRepository", "getLosByLoRepository");
617         renames.put("LearningObjectiveService.getLoCategoriesForLo", "getLoCategoriesByLo");
618         renames.put("LrcService.getResultComponent", "getResultValuesGroup");
619         renames.put("LuService.getClusByIdList", "getClusByIds");
620         renames.put("LuService.getAllowedLuLuRelationTypesByCluId", "getAllowedCluCluRelationTypesByClu");
621         renames.put("LuService.getClusByRelation", "getClusByRelatedCluAndRelationType");
622         renames.put("LuService.getCluIdsByRelation", "getCluIdsByRelatedCluAndRelationType");
623         renames.put("LuService.getRelatedClusByCluId", "getRelatedClusByCluAndRelationType");
624         renames.put("LuService.getRelatedCluIdsByCluId", "getRelatedCluIdsByCluAndRelationType");
625         renames.put("LuService.getCluPublicationsByCluId", "getCluPublicationsByClu");
626         renames.put("LuService.getResourceRequirementsForCluId", "getResourceRequirementsForClu");
627         renames.put("LuService.getCluSetInfo", "getCluSet");
628         renames.put("LuService.getCluSetInfoByIdList", "getCluSetsByIds");
629         renames.put("LuService.getLuisByIdList", "getLuisByIds");
630         renames.put("ProgramService.getMajorIdsByCredentialProgramType", "getMajorDisciplineIdsByCredentialProgramType");
631         renames.put("ProgramService.getVariationsByMajorDisciplineId", "getProgramVariationsByMajorDiscipline");
632         renames.put("ProgramService.getHonorsByCredentialProgramType", "getHonorProgramIdsByCredentialProgramType");
633         renames.put("ProposalService.getProposalsByIdList", "getProposalsByIds");
634         renames.put("", "");
635         renames.put("", "");
636         knownMethodRenames = renames;
637         return;
638     }
639 
640       private Map<String, String> knownMethodIssues = null;
641 
642     private void loadKnownMethodIssues() {
643         Map<String, String> issues = new HashMap<String, String>();
644         issues.put("AtpService.validateDateRange", "Dropped because DateRange objects were merged in with milestones");
645         issues.put("AtpService.getDateRange", "Dropped because DateRange objects were merged in with milestones");
646         issues.put("AtpService.getDateRangesByAtp", "Dropped because DateRange objects were merged in with milestones");
647         issues.put("AtpService.getDateRangesByDate", "Dropped because DateRange objects were merged in with milestones");
648         issues.put("AtpService.addDateRange", "Dropped because DateRange objects were merged in with milestones");
649         issues.put("AtpService.updateDateRange", "Dropped because DateRange objects were merged in with milestones");
650         issues.put("AtpService.removeDateRange", "Dropped because DateRange objects were merged in with milestones");
651         issues.put("DictionaryService.getObjectTypes", "Dictionary service was completely revamped to match KRAD, old one is still around use that for R1 stuff");
652         issues.put("DictionaryService.getObjectStructure", "Dictionary service was completely revamped to match KRAD, old one is still around use that for R1 stuff");
653         issues.put("CommentService.getCommentsByType", "Renamed and changed to just get Ids, so use getCommentIdsByType then call getCommentsByIds");
654         issues.put("CommentService.getTagsByType", "Renamed and changed to just get Ids, so use getTagIdsByType then call getTagsByIds");
655         issues.put("DocumentService.getRefObjectTypes", "(!) has been dropped from the contract, the document service should store any uri");
656         issues.put("DocumentService.getRefObjectSubTypes", "(!) has been dropped from the contract, the document service should store any uri and sub-object URI");
657         issues.put("OrganizationService.getOrgOrgRelationsByRelatedOrg", " (!) the two methods for tranversing by one side of the relationship or other has replaced by a single method that finds relationships no matter which side it is on (?) Need to possibly rethink this it imposes a big change on both the implementation and on the the application. ");        
658         issues.put("OrganizationService.getPersonIdsForOrgByRelationType", "Was removed, instead use getOrgPersonRelationsByTypeAndPerson and loop through the relationships to get the list of personIds that you want.  The issue was the old method did not take into account relationships that are old/inactive so using it would lead to errors that would only appear once transitions occured in the people being related to the org.");
659         issues.put("OrganizationService.getOrgPersonRelationsByPerson", "Renamd to getOrgPersonRelationsByOrgAndPerson, because the R1 was badly named, it said just by person but the parameters required an Org as well!");
660         issues.put("OrganizationService.getPositionRestrictionsByOrg", "use getOrgPositionRestrictionIdsByOrg then call getOrgPositionRestrictionsByIds to get the objects");
661         issues.put("LearningObjectiveService.getAllowedLoLoRelationTypesForLoType", "is a type method, use Type Service instead");
662         issues.put("LrcService.getCredential", "Is a Class 2 concept and as dropped from the Class 1 service");
663         issues.put("LrcService.getCredentialsByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service");
664         issues.put("LrcService.getCredentialKeysByCredentialType", "Is a Class 2 concept and as dropped from the Class 1 service");
665         issues.put("LrcService.getCredit", "Is a Class 2 concept and as dropped from the Class 1 service");
666         issues.put("LrcService.getCreditsByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service");
667         issues.put("LrcService.getCreditKeysByCreditType", "Is a Class 2 concept and as dropped from the Class 1 service");
668         issues.put("LrcService.getGrade", "Is a Class 2 concept and as dropped from the Class 1 service");
669         issues.put("LrcService.getGradesByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service");
670         issues.put("LrcService.getGradeKeysByGradeType", "Is a Class 2 concept and as dropped from the Class 1 service");
671         issues.put("LrcService.getGradesByScale", "Is a Class 2 concept and as dropped from the Class 1 service");
672         issues.put("LrcService.translateGrade", "(-) is not being supported at this time, translations will be added later");
673         issues.put("LrcService.compareGrades", "(-) is not being supported at this time, comparisons will be added later");
674         issues.put("LrcService.getResultComponentIdsByResultComponentType", "roughly maps to getResultValuesGroupIdsByType but they are different objects and the types have changed as well");
675         issues.put("LrcService.getResultComponentIdsByResult", "roughly maps to getResultValuesGroupsByResultValue but doesn't take the extra type parameter");
676         issues.put("LrcService.createResultComponent", "rougly maps to createResultValuesGroup");
677         issues.put("LrcService.updateResultComponent", "rougly maps to updateResultValuesGroup");
678         issues.put("LrcService.deleteResultComponent", "rougly maps to deleteResultValuesGroup");
679         issues.put("LrcService.getScale", "roughly maps to getResultScale");
680         issues.put("LuService.getAllowedLuLuRelationTypesByLuiId", "is a type method, use TypeService instead");
681         issues.put("", "");
682         issues.put("", "");
683         issues.put("", "");
684         issues.put("", "");
685         knownMethodIssues = issues;
686         return;
687     }
688     
689     
690     private ServiceMethod findMethod2(String serviceKey, String methodName) {
691         ServiceMethod method2 = finder2.findServiceMethod(serviceKey, methodName);
692         if (method2 == null) {
693             if (serviceKey.equals("Lu")) {
694                 method2 = finder2.findServiceMethod("Clu", methodName);
695                 if (method2 == null) {
696                     method2 = finder2.findServiceMethod("Lui", methodName);
697                 }
698             }
699         }
700         return method2;
701     }
702 
703     private String calcMethods(ServiceMethod method1) {
704         StringBuilder bldr = new StringBuilder();
705         String comma = "";
706         for (ServiceMethod method2 : finder2.findServiceMethods(method1.getService())) {
707             bldr.append(comma);
708             comma = ", ";
709             bldr.append(method2.getName());
710         }
711         return bldr.toString();
712     }
713 
714     private String calcPossibleMethods(ServiceMethod method1) {
715         StringBuilder bldr = new StringBuilder();
716         String comma = "";
717         for (ServiceMethod method2 : findPossibleMethods(method1)) {
718             bldr.append(comma);
719             comma = ", ";
720             bldr.append(method2.getName());
721         }
722         return bldr.toString();
723     }
724 
725     private List<ServiceMethod> findPossibleMethods(ServiceMethod method1) {
726         List<ServiceMethod> methods = new ArrayList<ServiceMethod>();
727         List<ServiceMethod> wideNet = null;
728         if (method1.getService().equals("Lu")) {
729             wideNet = finder2.findServiceMethods("Clu");
730             wideNet.addAll(finder2.findServiceMethods("Lui"));
731         } else {
732             wideNet = finder2.findServiceMethods(method1.getService());
733         }
734         for (ServiceMethod method2 : wideNet) {
735             if (isPossibleMatch(method1, method2)) {
736                 methods.add(method2);
737             }
738         }
739         return methods;
740     }
741 
742     private boolean isPossibleMatch(ServiceMethod method1, ServiceMethod method2) {
743          if (method1.getName().contains(method2.getName())) {
744             return true;
745         }
746         if (method2.getName().contains(method1.getName())) {
747             return true;
748         }
749         if (method1.getName().startsWith("get") && method2.getName().startsWith("get")) {
750             return true;
751         }
752         if (method1.getName().startsWith("add") && method2.getName().startsWith("create")) {
753             return true;
754         }
755         if (method1.getName().startsWith("create") && method2.getName().startsWith("create")) {
756             return true;
757         }
758         if (method1.getName().startsWith("update") && method2.getName().startsWith("update")) {
759             return true;
760         }
761         if (method1.getName().startsWith("delete") && method2.getName().startsWith("delete")) {
762             return true;
763         }
764         if (method1.getName().startsWith("remove") && method2.getName().startsWith("delete")) {
765             return true;
766         }
767         if (method1.getName().startsWith("validate") && method2.getName().startsWith("validate")) {
768             return true;
769         }
770         return false;
771     }
772 
773     private boolean isTypeMethod(ServiceMethod method1) {
774         if (method1.getReturnValue().getType().endsWith("TypeInfo")) {
775             return true;
776         }
777         if (method1.getReturnValue().getType().endsWith("TypeInfoList")) {
778             return true;
779         }
780         return false;
781     }
782 }