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("", "");
620         renames.put("", "");
621         renames.put("", "");
622         renames.put("", "");
623         renames.put("", "");
624         knownMethodRenames = renames;
625         return;
626     }
627 
628       private Map<String, String> knownMethodIssues = null;
629 
630     private void loadKnownMethodIssues() {
631         Map<String, String> issues = new HashMap<String, String>();
632         issues.put("AtpService.validateDateRange", "Dropped because DateRange objects were merged in with milestones");
633         issues.put("AtpService.getDateRange", "Dropped because DateRange objects were merged in with milestones");
634         issues.put("AtpService.getDateRangesByAtp", "Dropped because DateRange objects were merged in with milestones");
635         issues.put("AtpService.getDateRangesByDate", "Dropped because DateRange objects were merged in with milestones");
636         issues.put("AtpService.addDateRange", "Dropped because DateRange objects were merged in with milestones");
637         issues.put("AtpService.updateDateRange", "Dropped because DateRange objects were merged in with milestones");
638         issues.put("AtpService.removeDateRange", "Dropped because DateRange objects were merged in with milestones");
639         issues.put("DictionaryService.getObjectTypes", "Dictionary service was completely revamped to match KRAD, old one is still around use that for R1 stuff");
640         issues.put("DictionaryService.getObjectStructure", "Dictionary service was completely revamped to match KRAD, old one is still around use that for R1 stuff");
641         issues.put("CommentService.getCommentsByType", "Renamed and changed to just get Ids, so use getCommentIdsByType then call getCommentsByIds");
642         issues.put("CommentService.getTagsByType", "Renamed and changed to just get Ids, so use getTagIdsByType then call getTagsByIds");
643         issues.put("DocumentService.getRefObjectTypes", "Use type service but (!) there is no getRefObjectUris () method");
644         issues.put("DocumentService.getRefObjectSubTypes", "Use type service but (!) but do not have a refObject 'subtype' defined");
645         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. ");        
646         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.");
647         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!");
648         issues.put("OrganizationService.getPositionRestrictionsByOrg", "use getOrgPositionRestrictionIdsByOrg then call getOrgPositionRestrictionsByIds to get the objects");
649         issues.put("LearningObjectiveService.getAllowedLoLoRelationTypesForLoType", "is a type method, use Type Service instead");
650         issues.put("LrcService.getCredential", "Is a Class 2 concept and as dropped from the Class 1 service");
651         issues.put("LrcService.getCredentialsByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service");
652         issues.put("LrcService.getCredentialKeysByCredentialType", "Is a Class 2 concept and as dropped from the Class 1 service");
653         issues.put("LrcService.getCredit", "Is a Class 2 concept and as dropped from the Class 1 service");
654         issues.put("LrcService.getCreditsByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service");
655         issues.put("LrcService.getCreditKeysByCreditType", "Is a Class 2 concept and as dropped from the Class 1 service");
656         issues.put("LrcService.getGrade", "Is a Class 2 concept and as dropped from the Class 1 service");
657         issues.put("LrcService.getGradesByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service");
658         issues.put("LrcService.getGradeKeysByGradeType", "Is a Class 2 concept and as dropped from the Class 1 service");
659         issues.put("LrcService.getGradesByScale", "Is a Class 2 concept and as dropped from the Class 1 service");
660         issues.put("LrcService.translateGrade", "(-) is not being supported at this time, translations will be added later");
661         issues.put("LrcService.compareGrades", "(-) is not being supported at this time, comparisons will be added later");
662         issues.put("LrcService.getResultComponentIdsByResultComponentType", "roughly maps to getResultValuesGroupIdsByType but they are different objects and the types have changed as well");
663         issues.put("LrcService.getResultComponentIdsByResult", "roughly maps to getResultValuesGroupsByResultValue but doesn't take the extra type parameter");
664         issues.put("LrcService.createResultComponent", "rougly maps to createResultValuesGroup");
665         issues.put("LrcService.updateResultComponent", "rougly maps to updateResultValuesGroup");
666         issues.put("LrcService.deleteResultComponent", "rougly maps to deleteResultValuesGroup");
667         issues.put("LrcService.getScale", "roughly maps to getResultScale");
668         issues.put("", "");
669         issues.put("", "");
670         issues.put("", "");
671         issues.put("", "");
672         knownMethodIssues = issues;
673         return;
674     }
675     
676     
677     private ServiceMethod findMethod2(String serviceKey, String methodName) {
678         ServiceMethod method2 = finder2.findServiceMethod(serviceKey, methodName);
679         if (method2 == null) {
680             if (serviceKey.equals("Lu")) {
681                 method2 = finder2.findServiceMethod("Clu", methodName);
682                 if (method2 == null) {
683                     method2 = finder2.findServiceMethod("Lui", methodName);
684                 }
685             }
686         }
687         return method2;
688     }
689 
690     private String calcMethods(ServiceMethod method1) {
691         StringBuilder bldr = new StringBuilder();
692         String comma = "";
693         for (ServiceMethod method2 : finder2.findServiceMethods(method1.getService())) {
694             bldr.append(comma);
695             comma = ", ";
696             bldr.append(method2.getName());
697         }
698         return bldr.toString();
699     }
700 
701     private String calcPossibleMethods(ServiceMethod method1) {
702         StringBuilder bldr = new StringBuilder();
703         String comma = "";
704         for (ServiceMethod method2 : findPossibleMethods(method1)) {
705             bldr.append(comma);
706             comma = ", ";
707             bldr.append(method2.getName());
708         }
709         return bldr.toString();
710     }
711 
712     private List<ServiceMethod> findPossibleMethods(ServiceMethod method1) {
713         List<ServiceMethod> methods = new ArrayList<ServiceMethod>();
714         List<ServiceMethod> wideNet = null;
715         if (method1.getService().equals("Lu")) {
716             wideNet = finder2.findServiceMethods("Clu");
717             wideNet.addAll(finder2.findServiceMethods("Lui"));
718         } else {
719             wideNet = finder2.findServiceMethods(method1.getService());
720         }
721         for (ServiceMethod method2 : wideNet) {
722             if (isPossibleMatch(method1, method2)) {
723                 methods.add(method2);
724             }
725         }
726         return methods;
727     }
728 
729     private boolean isPossibleMatch(ServiceMethod method1, ServiceMethod method2) {
730          if (method1.getName().contains(method2.getName())) {
731             return true;
732         }
733         if (method2.getName().contains(method1.getName())) {
734             return true;
735         }
736         if (method1.getName().startsWith("get") && method2.getName().startsWith("get")) {
737             return true;
738         }
739         if (method1.getName().startsWith("add") && method2.getName().startsWith("create")) {
740             return true;
741         }
742         if (method1.getName().startsWith("create") && method2.getName().startsWith("create")) {
743             return true;
744         }
745         if (method1.getName().startsWith("update") && method2.getName().startsWith("update")) {
746             return true;
747         }
748         if (method1.getName().startsWith("delete") && method2.getName().startsWith("delete")) {
749             return true;
750         }
751         if (method1.getName().startsWith("remove") && method2.getName().startsWith("delete")) {
752             return true;
753         }
754         if (method1.getName().startsWith("validate") && method2.getName().startsWith("validate")) {
755             return true;
756         }
757         return false;
758     }
759 
760     private boolean isTypeMethod(ServiceMethod method1) {
761         if (method1.getReturnValue().getType().endsWith("TypeInfo")) {
762             return true;
763         }
764         if (method1.getReturnValue().getType().endsWith("TypeInfoList")) {
765             return true;
766         }
767         return false;
768     }
769 }