001/** 002 * Copyright 2004-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.student.contract.model.impl; 017 018import java.io.ByteArrayOutputStream; 019import java.io.File; 020import java.io.PrintStream; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Date; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.LinkedHashSet; 027import java.util.List; 028import java.util.Map; 029import java.util.Set; 030import org.junit.After; 031import org.junit.AfterClass; 032import org.junit.Before; 033import org.junit.BeforeClass; 034import org.junit.Test; 035import static org.junit.Assert.*; 036import org.junit.Ignore; 037 038import org.kuali.student.contract.model.MessageStructure; 039import org.kuali.student.contract.model.Service; 040import org.kuali.student.contract.model.ServiceContractModel; 041import org.kuali.student.contract.model.ServiceMethod; 042import org.kuali.student.contract.model.ServiceMethodParameter; 043import org.kuali.student.contract.model.XmlType; 044import org.kuali.student.contract.model.util.HtmlContractMessageStructureWriter; 045import org.kuali.student.contract.model.util.ModelFinder; 046import org.kuali.student.contract.model.validation.ServiceContractModelValidator; 047 048/** 049 * 050 * @author nwright 051 */ 052@Ignore 053public class M6M7ServiceContractComparisonTest { 054 055 public M6M7ServiceContractComparisonTest() { 056 } 057 058 @BeforeClass 059 public static void setUpClass() throws Exception { 060 } 061 062 @AfterClass 063 public static void tearDownClass() throws Exception { 064 } 065 private ByteArrayOutputStream baos; 066 private PrintStream out; 067 068 @Before 069 public void setUp() { 070 baos = new ByteArrayOutputStream(); 071 out = new PrintStream(baos); 072 073 out.println("This section was created by programmatically comparing the message structures."); 074 out.println("Run on: " + new Date()); 075 out.println("See [M6M7ServiceContractComparisonTest.java|https://test.kuali.org/svn/student/tools/maven-kscontractdoc-plugin/trunk/src/test/java/org/kuali/student/contract/model/impl/M6M7ServiceContractComparisonTest.java]"); 076 out.println(""); 077 out.println("Legend:"); 078 out.println("* (-) Removed or dropped from contract"); 079 out.println("* (+) Added to contract"); 080 out.println("* (/) Renamed in contract"); 081 out.println("* (*y) Change to contract"); 082 out.println("* (!) Deprecated"); 083 out.println(""); 084 out.println("*TABLE OF CONTENTS*"); 085 out.println("{toc}"); 086 out.println(""); 087 out.println("h1. Loading models of the contracts from the source code"); 088 out.println("h2. Log from loading model for M6"); 089 getModelM6(); 090 out.println("h2. Log from loading model for M7"); 091 getModelM7(); 092 getFinderM6(); 093 getFinderM7(); 094 loadKnownObjectRenames(); 095 loadKnownUnconvertedObjects(); 096 loadKnownFieldRenames(); 097 loadKnownFieldIssues(); 098 loadKnownMethodRenames(); 099 loadKnownMethodIssues(); 100 } 101 102 @After 103 public void tearDown() { 104 if (baos != null) { 105 System.out.append(baos.toString()); 106 } 107 } 108 private static final String RESOURCES_DIRECTORY = "src/test/resources"; 109 private static final String TEST_SOURCE_DIRECTORY = 110 "src/test/java/org/kuali/student/contract/model/test/source"; 111 private static final String M6_PROJECT_API_DIRECTORY = "D:/svn/ks/trunk/ks-api"; 112 private static final String M6_COMMON_API_DIRECTORY = M6_PROJECT_API_DIRECTORY + "/ks-common-api/src/main/java"; 113 private static final String M6_CORE_API_DIRECTORY = M6_PROJECT_API_DIRECTORY + "/ks-core-api/src/main/java"; 114 private static final String M6_LUM_API_DIRECTORY = M6_PROJECT_API_DIRECTORY + "/ks-lum-api/src/main/java"; 115 private static final String M6_ENROLL_API_DIRECTORY = M6_PROJECT_API_DIRECTORY + "/ks-enroll-api/src/main/java"; 116 private static final String M7_PROJECT_API_DIRECTORY = "D:/svn/ks/services/ks-api"; 117 private static final String M7_COMMON_API_DIRECTORY = M7_PROJECT_API_DIRECTORY + "/ks-common-api/src/main/java"; 118 private static final String M7_CORE_API_DIRECTORY = M7_PROJECT_API_DIRECTORY + "/ks-core-api/src/main/java"; 119 private static final String M7_LUM_API_DIRECTORY = M7_PROJECT_API_DIRECTORY + "/ks-lum-api/src/main/java"; 120 private static final String M7_ENROLL_API_DIRECTORY = M7_PROJECT_API_DIRECTORY + "/ks-enroll-api/src/main/java"; 121 private static ServiceContractModel modelM6 = null; 122 private static ServiceContractModel modelM7 = null; 123 private Map<String, String> knownMethodRenames = null; 124 private Map<String, String> knownFieldRenames = null; 125 private Map<String, String> knownMethodIssues = null; 126 private Map<String, String> knownUnconvertedObjects = null; 127 128 /** 129 * Test of getServiceMethods method, of class 130 * ServiceContractModelQDoxLoader. 131 */ 132 @Test 133 public void testCompareModels() { 134 out.println(""); 135 out.println("h1. Message Structure Comparison"); 136 compareTypes(); 137 out.println(""); 138 out.println("h1. Service Method Comparison"); 139 compareMethods(); 140 } 141 142 private ServiceContractModel getModelM6() { 143 if (modelM6 != null) { 144 return modelM6; 145 } 146 List<String> srcDirs = new ArrayList(); 147 out.println("User directory=" + System.getProperty("user.dir")); 148 out.println("Current directory=" + new File(".").getAbsolutePath()); 149 srcDirs.add(M6_COMMON_API_DIRECTORY); 150 srcDirs.add(M6_CORE_API_DIRECTORY); 151 srcDirs.add(M6_LUM_API_DIRECTORY); 152 srcDirs.add(M6_ENROLL_API_DIRECTORY); 153 out.println("Reading as input:"); 154 for (String directory : srcDirs) { 155 out.println("* " + directory); 156 } 157 out.println(""); 158 ServiceContractModel instance = new ServiceContractModelQDoxLoader(srcDirs); 159 160 instance = new ServiceContractModelCache(instance); 161 validate(instance); 162 modelM6 = instance; 163 return instance; 164 } 165 166 private ServiceContractModel getModelM7() { 167 if (modelM7 != null) { 168 return modelM7; 169 } 170 List<String> srcDirs = new ArrayList(); 171 out.println("User directory=" + System.getProperty("user.dir")); 172 out.println("Current directory=" + new File(".").getAbsolutePath()); 173 srcDirs.add(M7_COMMON_API_DIRECTORY); 174 srcDirs.add(M7_CORE_API_DIRECTORY); 175 srcDirs.add(M7_LUM_API_DIRECTORY); 176 srcDirs.add(M7_ENROLL_API_DIRECTORY); 177 out.println("Reading as input:"); 178 for (String directory : srcDirs) { 179 out.println("* " + directory); 180 } 181 out.println(""); 182 ServiceContractModel instance = new ServiceContractModelQDoxLoader(srcDirs); 183 184 instance = new ServiceContractModelCache(instance); 185 validate(instance); 186 modelM7 = instance; 187 return instance; 188 } 189 190 private String dump(ServiceMethod method) { 191 StringBuilder bldr = new StringBuilder(); 192 bldr.append(method.getName()); 193 String comma = ""; 194 bldr.append("("); 195 for (ServiceMethodParameter param : method.getParameters()) { 196 bldr.append(comma); 197 comma = ", "; 198 bldr.append(param.getType()); 199 bldr.append(" "); 200 bldr.append(param.getName()); 201 } 202 bldr.append(")"); 203 return bldr.toString(); 204 } 205 206 private void validate(ServiceContractModel model) { 207 Collection<String> errors = 208 new ServiceContractModelValidator(model).validate(); 209 if (errors.size() > 0) { 210 StringBuilder buf = new StringBuilder(); 211 buf.append(errors.size()).append(" errors found while validating the data."); 212 int cnt = 0; 213 for (String msg : errors) { 214 cnt++; 215 buf.append("\n"); 216 buf.append("*error*").append(cnt).append(":").append(msg); 217 } 218 219 fail(buf.toString()); 220 } 221 } 222 private ModelFinder finderM6 = null; 223 224 private ModelFinder getFinderM6() { 225 if (finderM6 == null) { 226 finderM6 = new ModelFinder(getModelM6()); 227 } 228 return finderM6; 229 } 230 private ModelFinder finderM7 = null; 231 232 private ModelFinder getFinderM7() { 233 if (finderM7 == null) { 234 finderM7 = new ModelFinder(getModelM7()); 235 } 236 return finderM7; 237 } 238 239 private void compareTypes() { 240 for (Service service : modelM6.getServices()) { 241 Set<String> found = new LinkedHashSet<String>(); 242 out.println(""); 243 out.println("h2. " + service.getName() + " Structures"); 244 for (XmlType xmlTypeM6 : finderM6.findAllComplexTypesInService(service.getKey())) { 245 XmlType xmlTypeM7 = findCompareType(xmlTypeM6); 246 if (xmlTypeM7 != null) { 247 found.add(xmlTypeM7.getName()); 248 } 249 } 250 for (XmlType xmlTypeM7 : finderM7.findAllComplexTypesInService(service.getKey())) { 251 if (!found.contains(xmlTypeM7.getName())) { 252 out.println("# (+) " + xmlTypeM7.getName() + ": was added in M7"); 253 } 254 } 255 } 256 } 257 258 private String calcService(XmlType xmlType) { 259 StringBuilder bldr = new StringBuilder(); 260 String comma = ""; 261 for (String serviceKey : HtmlContractMessageStructureWriter.calcUsageByService(modelM6, xmlType)) { 262 bldr.append(comma); 263 comma = ", "; 264 bldr.append(serviceKey); 265 } 266 return bldr.toString(); 267 } 268 269 private String calcFieldNames(XmlType xmlType) { 270 StringBuilder bldr = new StringBuilder(); 271 String comma = ""; 272 for (MessageStructure ms : finderM7.findMessageStructures(xmlType.getName())) { 273 bldr.append(comma); 274 comma = ", "; 275 bldr.append(ms.getShortName()); 276 } 277 return bldr.toString(); 278 } 279 280 private void loadKnownUnconvertedObjects() { 281 Map<String, String> missings = new HashMap<String, String>(); 282// missings.put("ObjectStructureDefinition", "Old M6 dictionary not converted"); 283// missings.put("FieldDefinition", "Old M6 dictionary not converted"); 284// missings.put("ValidCharsConstraint", "Old M6 dictionary not converted"); 285// missings.put("RequiredConstraint", "Old M6 dictionary not converted"); 286// missings.put("CaseConstraint", "Old M6 dictionary not converted"); 287// missings.put("WhenConstraint", "Old M6 dictionary not converted"); 288// missings.put("Constraint", "Old M6 dictionary not converted"); 289// missings.put("MustOccurConstraint", "Old M6 dictionary not converted"); 290// missings.put("LookupConstraint", "Old M6 dictionary not converted"); 291// missings.put("CommonLookupParam", "Old M6 dictionary not converted"); 292// missings.put("CommonLookup", "Old M6 dictionary not converted"); 293// missings.put("DateRangeInfo", "DateRange was merged in with Milestone"); 294// missings.put("CredentialInfo", "LRC was revamped and Class II like objects were dropped"); 295// missings.put("CreditInfo", "LRC was revamped and Class II like objects were dropped"); 296// missings.put("ScaleInfo", "Changed to be ResultScaleInfo"); 297// missings.put("GradeInfo", "LRC was revamped and Class II like objects were dropped"); 298// missings.put("ResultComponentInfo", "Changed to be ResultValuesGroupInfo"); 299// 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"); 300// missings.put("FieldDescriptor", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 301// missings.put("SearchSelector", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 302// missings.put("ObjectStructure", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 303// missings.put("Type", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 304// missings.put("State", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 305// missings.put("Field", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 306// missings.put("ConstraintDescriptor", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 307// missings.put("ConstraintSelector", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 308// missings.put("RequireConstraint", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 309// missings.put("TypeStateCaseConstraint", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 310// missings.put("TypeStateWhenConstraint", "Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 311// missings.put("OccursConstraint", " Old pre-M6 dictionary structure that were attached to search param types were dropped -- ui dictionary provided that info"); 312// 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"); 313// 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"); 314// missings.put("java.lang.String", ""); 315// missings.put("Map<String, String>", ""); 316// missings.put("LuiInfo", "Lui was pulled out and put in it's own service. The LuiInfo object was not used in M6 and was radically redesigned in M7"); 317 318 knownUnconvertedObjects = missings; 319 return; 320 } 321 private Map<String, String> knownObjectRenames = null; 322 323 private void loadKnownObjectRenames() { 324 Map<String, String> renames = new HashMap<String, String>(); 325// renames.put("Message", "MessageInfo"); 326// renames.put("SearchRequest", "SearchRequestInfo"); 327// renames.put("SearchResult", "SearchResultInfo"); 328// renames.put("SearchParam", "SearchParamInfo"); 329// renames.put("SearchResultRow", "SearchResultRowInfo"); 330// renames.put("SearchResultCell", "SearchResultCellInfo"); 331// renames.put("Message", "MessageInfo"); 332 knownObjectRenames = renames; 333 return; 334 } 335 336 private void loadKnownFieldRenames() { 337 Map<String, String> renames = new HashMap<String, String>(); 338 renames.put("OrgCodeInfo.key", "OrgCodeInfo.typeKey"); // not all the time but when it happens want to catch if id not found 339// renames.put("desc", "descr"); 340// renames.put("state", "stateKey"); 341// renames.put("type", "typeKey"); 342// renames.put("metaInfo", "meta"); 343// renames.put("desc", "descr"); 344// renames.put("startTerm", "startTermId"); 345// renames.put("endTerm", "endTermId"); 346// renames.put("longDesc", "longDescr"); 347// renames.put("shortDesc", "shortDescr"); 348// renames.put("objectTypeURI", "refObjectUri"); 349// // TODO: this works but really should make these specific to the object they are connected with 350// renames.put("detailDesc", "descr"); 351// renames.put("milestoneDate", "startDate"); 352// renames.put("success", "isSuccess"); 353// renames.put("relationType", "relationTypeKey"); 354// renames.put("unitType", "unitTypeKey"); 355// renames.put("enrollable", "isEnrollable"); 356// renames.put("hazardousForDisabledStudents", "isHazardousForDisabledStudents"); 357// renames.put("versionInfo", "version"); 358// renames.put("primary", "isPrimary"); 359// renames.put("activityType", "typeKey"); 360// renames.put("loRepository", "loRepositoryKey"); 361// renames.put("queryParamValueList", "queryParamValues"); 362// renames.put("credentialProgramType", "typeKey"); 363 knownFieldRenames = renames; 364 return; 365 } 366 private Map<String, String> knownFieldIssues = null; 367 368 private void loadKnownFieldIssues() { 369 Map<String, String> issues = new HashMap<String, String>(); 370// issues.put("AtpInfo.key", "Switched from key to Id"); 371// issues.put("MilestoneInfo.key", "Switched from key to Id"); 372// issues.put("AtpInfo.id", ""); // suppress the extra field message from the m7 side 373// issues.put("MilestoneInfo.id", ""); // ditto 374// issues.put("MilestoneInfo.atpId", "Is not in M7 because a Milestone can be connected to more than one ATP so it is managed through a relationship"); 375// issues.put("Message.locale", "the type was changed from String to LocaleInfo to hold the different parts of the locale info"); 376// issues.put("SearchRequest.params", ""); 377// issues.put("SearchResult.rows", ""); 378// issues.put("SearchResultRow.cells", ""); 379// issues.put("ValidationResultInfo.errorLevel", ""); 380// issues.put("ValidationResultInfo.level", ""); 381// issues.put("ValidationResultInfo.ok", ""); 382// issues.put("ValidationResultInfo.warn", ""); 383// issues.put("ValidationResultInfo.error", ""); 384// issues.put("DocumentInfo.documentBinaryInfo", "renamd to just documentBinary (removing the trailing Info from the field name)"); 385// issues.put("OrgHierarchyInfo.key", "Switched from key to Id"); 386// issues.put("SearchResultTypeInfo.resultColumns", "ResultColumns is really anotther type to describe the column, Use type-type relation to hold that info"); 387// issues.put("ReqCompFieldTypeInfo.fieldDescriptor", "was dropped because it was an Old Pre-M6 dictionary and was not used -- UI dictionary provides that info instead"); 388// 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"); 389// 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"); 390// issues.put("SearchCriteriaTypeInfo.queryParams", "Query Params is a TypeInfo that describes the parameter, model as type and type-type relation"); 391// issues.put("OrgOrgRelationTypeInfo.orgHierarchyKey", "This was removed because a particular relation type can participate in more than one hierarchies!"); 392// issues.put("SearchParam.value", "Renamed to values which is List<String>, in M6 the setValue method was overloaded to take a string or List, Kept in M7 but marked as deprecated"); 393// issues.put("", ""); 394// issues.put("", ""); 395// issues.put("", ""); 396// issues.put("", ""); 397// issues.put("", ""); 398// issues.put("", ""); 399// issues.put("", ""); 400// issues.put("", ""); 401// issues.put("", ""); 402// issues.put("", ""); 403 404 knownFieldIssues = issues; 405 return; 406 } 407 408 private void loadKnownMethodRenames() { 409 Map<String, String> renames = new HashMap<String, String>(); 410// renames.put("AtpService.getAtpsByAtpType", "getAtpIdsByType"); 411// renames.put("AtpService.getMilestonesByAtp", "getMilestonesForAtp"); 412// renames.put("AtpService.addMilestone", "addMilestoneToAtp"); 413// renames.put("AtpService.removeMilestone", "removeMilestoneFromAtp"); 414// renames.put("MessageService.getMessageGroups", "getMessageGroupKeys"); 415// renames.put("CommentService.getComments", "getCommentsByReferenceAndType"); 416// renames.put("CommentService.getTags", "getTagsByReferenceAndType"); 417// renames.put("CommentService.addTag", "createTag"); 418// renames.put("CommentService.addComment", "createComment"); 419// renames.put("CommentService.removeComment", "deleteComment"); 420// renames.put("CommentService.removeTag", "deleteTag"); 421// renames.put("CommentService.removeComments", "deleteCommentsByReference"); 422// renames.put("CommentService.removeTags", "deleteTagsByReference"); 423// renames.put("DocumentService.getDocumentsByIdList", "getDocumentsByIds"); 424// renames.put("DocumentService.getCategoriesByDocument", "getDocumentCategoriesByDocumentId"); 425// renames.put("DocumentService.getRefDocRelationsByDoc", "getRefDocRelationsByDocument"); 426// renames.put("EnumerationManagementService.removeEnumeratedValue", "deleteEnumeratedValue"); 427// renames.put("OrganizationService.getOrganization", "getOrg"); 428// renames.put("OrganizationService.getOrganizationsByIdList", "getOrgsByIds"); 429// renames.put("OrganizationService.getOrgOrgRelationsByIdList", "getOrgOrgRelationsByIds"); 430// renames.put("OrganizationService.getOrgPersonRelationsByIdList", "getOrgPersonRelationsByIds"); 431// renames.put("OrganizationService.getPersonIdsForOrgByRelationType", ""); 432// renames.put("OrganizationService.getAllOrgPersonRelationsByPerson", "getOrgPersonRelationsByPerson"); 433// renames.put("OrganizationService.getAllOrgPersonRelationsByOrg", "getOrgPersonRelationsByOrg"); 434// renames.put("OrganizationService.createOrganization", "createOrg"); 435// renames.put("OrganizationService.updateOrganization", "updateOrg"); 436// renames.put("OrganizationService.deleteOrganization", "deleteOrg"); 437// renames.put("OrganizationService.validateOrganization", "validateOrg"); 438// renames.put("OrganizationService.removeOrgOrgRelation", "deleteOrgOrgRelation"); 439// renames.put("OrganizationService.removeOrgPersonRelation", "deleteOrgPersonRelation"); 440// renames.put("OrganizationService.addPositionRestrictionToOrg", "createOrgPositionRestriction"); 441// renames.put("OrganizationService.updatePositionRestrictionForOrg", "updateOrgPositionRestriction"); 442// renames.put("OrganizationService.removePositionRestrictionFromOrg", "deleteOrgPositionRestriction"); 443// renames.put("StatementService.getStatementsUsingReqComponent", "getStatementsByReqComponent"); 444// renames.put("StatementService.getStatementsUsingStatement", "getStatementsForStatement"); 445// renames.put("CourseService.getCourseFormats", "getCourseFormatsByCourse"); 446// renames.put("CourseService.getCourseActivities", "getCourseActivitiesByCourseFormat"); 447// renames.put("CourseService.getCourseLos", "getCourseLearningObjectivesByCourse"); 448// renames.put("LearningObjectiveService.getLoCategories", "getLoCategoriesByLoRepository"); 449// renames.put("LearningObjectiveService.getLoByIdList", "getLosByIds"); 450// renames.put("LearningObjectiveService.getLosByRepository", "getLosByLoRepository"); 451// renames.put("LearningObjectiveService.getLoCategoriesForLo", "getLoCategoriesByLo"); 452// renames.put("LrcService.getResultComponent", "getResultValuesGroup"); 453// renames.put("LuService.getClusByIdList", "getClusByIds"); 454// renames.put("LuService.getAllowedLuLuRelationTypesByCluId", "getAllowedCluCluRelationTypesByClu"); 455// renames.put("LuService.getClusByRelation", "getClusByRelatedCluAndRelationType"); 456// renames.put("LuService.getCluIdsByRelation", "getCluIdsByRelatedCluAndRelationType"); 457// renames.put("LuService.getRelatedClusByCluId", "getRelatedClusByCluAndRelationType"); 458// renames.put("LuService.getRelatedCluIdsByCluId", "getRelatedCluIdsByCluAndRelationType"); 459// renames.put("LuService.getCluPublicationsByCluId", "getCluPublicationsByClu"); 460// renames.put("LuService.getResourceRequirementsForCluId", "getResourceRequirementsForClu"); 461// renames.put("LuService.getCluSetInfo", "getCluSet"); 462// renames.put("LuService.getCluSetInfoByIdList", "getCluSetsByIds"); 463// renames.put("LuService.getLuisByIdList", "getLuisByIds"); 464// renames.put("ProgramService.getMajorIdsByCredentialProgramType", "getMajorDisciplineIdsByCredentialProgramType"); 465// renames.put("ProgramService.getVariationsByMajorDisciplineId", "getProgramVariationsByMajorDiscipline"); 466// renames.put("ProgramService.getHonorsByCredentialProgramType", "getHonorProgramIdsByCredentialProgramType"); 467// renames.put("ProposalService.getProposalsByIdList", "getProposalsByIds"); 468// renames.put("", ""); 469// renames.put("", ""); 470 knownMethodRenames = renames; 471 return; 472 } 473 474 private void loadKnownMethodIssues() { 475 Map<String, String> issues = new HashMap<String, String>(); 476// issues.put("AtpService.validateDateRange", "Dropped because DateRange objects were merged in with milestones"); 477// issues.put("AtpService.getDateRange", "Dropped because DateRange objects were merged in with milestones"); 478// issues.put("AtpService.getDateRangesByAtp", "Dropped because DateRange objects were merged in with milestones"); 479// issues.put("AtpService.getDateRangesByDate", "Dropped because DateRange objects were merged in with milestones"); 480// issues.put("AtpService.addDateRange", "Dropped because DateRange objects were merged in with milestones"); 481// issues.put("AtpService.updateDateRange", "Dropped because DateRange objects were merged in with milestones"); 482// issues.put("AtpService.removeDateRange", "Dropped because DateRange objects were merged in with milestones"); 483// issues.put("DictionaryService.getObjectTypes", "Dictionary service was completely revamped to match KRAD, old one is still around use that for M6 stuff"); 484// issues.put("DictionaryService.getObjectStructure", "Dictionary service was completely revamped to match KRAD, old one is still around use that for M6 stuff"); 485// issues.put("CommentService.getCommentsByType", "Renamed and changed to just get Ids, so use getCommentIdsByType then call getCommentsByIds"); 486// issues.put("CommentService.getTagsByType", "Renamed and changed to just get Ids, so use getTagIdsByType then call getTagsByIds"); 487// issues.put("DocumentService.getRefObjectTypes", "(!) has been dropped from the contract, the document service should store any uri"); 488// issues.put("DocumentService.getRefObjectSubTypes", "(!) has been dropped from the contract, the document service should store any uri and sub-object URI"); 489// 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. "); 490// 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."); 491// issues.put("OrganizationService.getOrgPersonRelationsByPerson", "Renamd to getOrgPersonRelationsByOrgAndPerson, because the M6 was badly named, it said just by person but the parameters required an Org as well!"); 492// issues.put("OrganizationService.getPositionRestrictionsByOrg", "use getOrgPositionRestrictionIdsByOrg then call getOrgPositionRestrictionsByIds to get the objects"); 493// issues.put("LearningObjectiveService.getAllowedLoLoRelationTypesForLoType", "is a type method, use Type Service instead"); 494// issues.put("LrcService.getCredential", "Is a Class 2 concept and as dropped from the Class 1 service"); 495// issues.put("LrcService.getCredentialsByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service"); 496// issues.put("LrcService.getCredentialKeysByCredentialType", "Is a Class 2 concept and as dropped from the Class 1 service"); 497// issues.put("LrcService.getCredit", "Is a Class 2 concept and as dropped from the Class 1 service"); 498// issues.put("LrcService.getCreditsByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service"); 499// issues.put("LrcService.getCreditKeysByCreditType", "Is a Class 2 concept and as dropped from the Class 1 service"); 500// issues.put("LrcService.getGrade", "Is a Class 2 concept and as dropped from the Class 1 service"); 501// issues.put("LrcService.getGradesByKeyList", "Is a Class 2 concept and as dropped from the Class 1 service"); 502// issues.put("LrcService.getGradeKeysByGradeType", "Is a Class 2 concept and as dropped from the Class 1 service"); 503// issues.put("LrcService.getGradesByScale", "Is a Class 2 concept and as dropped from the Class 1 service"); 504// issues.put("LrcService.translateGrade", "(-) is not being supported at this time, translations will be added later"); 505// issues.put("LrcService.compareGrades", "(-) is not being supported at this time, comparisons will be added later"); 506// issues.put("LrcService.getResultComponentIdsByResultComponentType", "roughly maps to getResultValuesGroupIdsByType but they are different objects and the types have changed as well"); 507// issues.put("LrcService.getResultComponentIdsByResult", "roughly maps to getResultValuesGroupsByResultValue but doesn't take the extra type parameter"); 508// issues.put("LrcService.createResultComponent", "rougly maps to createResultValuesGroup"); 509// issues.put("LrcService.updateResultComponent", "rougly maps to updateResultValuesGroup"); 510// issues.put("LrcService.deleteResultComponent", "rougly maps to deleteResultValuesGroup"); 511// issues.put("LrcService.getScale", "roughly maps to getResultScale"); 512// issues.put("LuService.getAllowedLuLuRelationTypesByLuiId", "is a type method, use TypeService instead"); 513// issues.put("", ""); 514// issues.put("", ""); 515// issues.put("", ""); 516// issues.put("", ""); 517 knownMethodIssues = issues; 518 return; 519 } 520 521 private XmlType findType(XmlType m6) { 522 XmlType m7 = finderM7.findXmlType(m6.getName()); 523 if (m7 == null) { 524 String renamedName = this.knownObjectRenames.get(m6.getName()); 525 if (renamedName != null) { 526 m7 = finderM7.findXmlType(renamedName); 527 if (m7 == null) { 528 out.println("# (-) " + m6.getName() + ": was not found even after being renamed to " + renamedName); 529 return null; 530 } 531 out.println("# (/) " + m6.getName() + ": was renamed to " + renamedName); 532 return m7; 533 } 534 } 535// if (m7 == null) { 536// if (m6.getName().endsWith("TypeInfo")) { 537// m7 = finderM7.findXmlType("TypeInfo"); 538// } 539// } 540 return m7; 541 } 542 543 private XmlType findCompareType(XmlType m6) { 544 if (m6.getName().endsWith("List")) { 545 return null; 546 } 547 if (this.knownUnconvertedObjects.containsKey(m6.getName())) { 548 String message = this.knownUnconvertedObjects.get(m6.getName()); 549 if (message.isEmpty()) { 550 return null; 551 } 552 out.println("# (-) " + m6.getName() + ":" + message); 553 return null; 554 } 555 XmlType m7 = findType(m6); 556 if (m7 == null) { 557 out.println("# (-) " + m6.getName() + ": has no corresponding object in M7"); 558 return m7; 559 } 560 Set<MessageStructure> usedInM7 = new HashSet<MessageStructure>(); 561 for (MessageStructure ms : finderM6.findMessageStructures(m6.getName())) { 562 MessageStructure used = findCompareMessageStructure(ms, m7); 563 if (used != null) { 564 usedInM7.add(used); 565 } 566 } 567 return m7; 568 } 569 570 private MessageStructure findCompareMessageStructure(MessageStructure m6, XmlType xmlTypeM7) { 571 MessageStructure m7 = findMessageStructure(m6, xmlTypeM7); 572 String issue = this.knownFieldIssues.get(m6.getXmlObject() + "." + m6.getShortName()); 573 if (issue != null) { 574 if (!issue.isEmpty()) { 575 out.println("# (*y) " + m6.getXmlObject() + "." + m6.getShortName() + ": " + issue); 576 } 577 return m7; 578 } 579 if (m7 == null) { 580 out.println("# (-) " + m6.getXmlObject() + "." + m6.getShortName() + " not found in M7: perhaps it was renamed to one of these? " + calcFieldNames(xmlTypeM7)); 581 return null; 582 } 583 compareType(m6, m7); 584 compareDeprecation(m6, m7); 585 return m7; 586 } 587 588 private void compareType(MessageStructure m6, MessageStructure m7) { 589 if (m6.getType().equalsIgnoreCase(m7.getType())) { 590 return; 591 } 592 out.println("# (*y) " + m6.getXmlObject() + "." + m6.getShortName() + ": the type was changed from " + m6.getType() + " to " + m7.getType()); 593 } 594 595 private void compareDeprecation(MessageStructure m6, MessageStructure m7) { 596 if (m6.isDeprecated() && m7.isDeprecated()) { 597 return; 598 } 599 if (!m6.isDeprecated() && !m7.isDeprecated()) { 600 return; 601 } 602 if (!m6.isDeprecated() && m7.isDeprecated()) { 603 out.println("# (!) " + m6.getXmlObject() + "." + m6.getShortName() + " has been deprecated and may be removed in future releases"); 604 return; 605 } 606 607 if (m6.isDeprecated() && !m7.isDeprecated()) { 608 out.println("# (!) " + m6.getXmlObject() + "." + m6.getShortName() + " had been dedprecated but is no longer marked as such"); 609 return; 610 } 611 throw new RuntimeException("should never reach here"); 612 } 613 614 private MessageStructure findMessageStructure(MessageStructure m6, XmlType xmlTypeM7) { 615 MessageStructure m7 = finderM7.findMessageStructure(xmlTypeM7.getName(), m6.getShortName()); 616 if (m7 == null) { 617 String renamed = this.knownFieldRenames.get(m6.getShortName()); 618 if (renamed != null) { 619 m7 = finderM7.findMessageStructure(xmlTypeM7.getName(), renamed); 620 if (m7 == null) { 621 out.println("# (-) " + m6.getXmlObject() + "." + m6.getShortName() 622 + " was renamed to " + xmlTypeM7.getName() + "." + renamed 623 + " BUT IT STILL DIDN'T EXIST IN M7"); 624 return null; 625 } 626 out.println("# (*y) " + m6.getXmlObject() + "." + m6.getShortName() 627 + " was renamed to " + xmlTypeM7.getName() + "." + renamed); 628 } 629 } 630 return m7; 631 } 632 633 private void compareMethods() { 634 for (Service service : modelM6.getServices()) { 635 Set<String> found = new LinkedHashSet<String>(); 636 out.println(""); 637 out.println("h2. " + service.getName() + " Methods"); 638 List<ServiceMethod> methodsInService = finderM6.findServiceMethods(service.getKey()); 639 for (ServiceMethod method : methodsInService) { 640 ServiceMethod methodM7 = findCompareMethod(method); 641 if (methodM7 != null) { 642 found.add(methodM7.getName()); 643 } 644 } 645 for (ServiceMethod methodM7 : finderM7.findServiceMethods(service.getKey())) { 646 if (!found.contains(methodM7.getName())) { 647 out.println("# (+) " + methodM7.getName() + ": was added in M7"); 648 } 649 } 650 } 651 } 652 653 private ServiceMethod findCompareMethod(ServiceMethod methodM6) { 654 String issue = knownMethodIssues.get(methodM6.getService() + "Service." + methodM6.getName()); 655 if (issue != null) { 656 if (!issue.isEmpty()) { 657 out.println("# (*y) " + methodM6.getService() + "Service." + methodM6.getName() 658 + ": " + issue); 659 } 660 return null; 661 } 662 ServiceMethod methodM7 = findMethod(methodM6); 663 if (methodM7 == null) { 664 String possibleMethods = this.calcPossibleMethods(methodM6); 665 if (possibleMethods.isEmpty()) { 666 out.println("# (-) " + methodM6.getService() + "Service." + methodM6.getName() 667 + " could not be found in M7"); 668 } else { 669 out.println("# (-) " + methodM6.getService() + "Service." + methodM6.getName() 670 + " does not exist in M7. It might have been renamed to one of these: " 671 + possibleMethods); 672 } 673 return null; 674 } 675 if (!methodM6.getName().equals(methodM7.getName())) { 676 out.println("# (*y) " + methodM6.getService() + "Service." + methodM6.getName() 677 + " was renamed to " + methodM7.getService() + "Service." + methodM7.getName()); 678 } 679 if (!doAllParametersMatch(methodM6, methodM7)) { 680 out.print("# (*y) " + methodM6.getService() + "Service." + methodM6.getName() 681 + " parameters changed from ("); 682 String comma = ""; 683 for (ServiceMethodParameter param : methodM6.getParameters()) { 684 out.print (comma); 685 comma = ", "; 686 out.print (param.getType() + " " + param.getName()); 687 } 688 out.print (") to ("); 689 comma = ""; 690 for (ServiceMethodParameter param : methodM7.getParameters()) { 691 out.print (comma); 692 comma = ", "; 693 out.print (param.getType() + " " + param.getName()); 694 } 695 out.println (")"); 696 } 697 return methodM7; 698 } 699 700 private boolean doAllParametersMatch(ServiceMethod methodM6, ServiceMethod methodM7) { 701 if (methodM6.getParameters().size() != methodM7.getParameters().size()) { 702 return false; 703 } 704 for (int i = 0; i < methodM6.getParameters().size(); i++) { 705 ServiceMethodParameter paramM6 = methodM6.getParameters().get(i); 706 ServiceMethodParameter paramM7 = methodM7.getParameters().get(i); 707 if (!doParametersMatch(paramM6, paramM7)) { 708 return false; 709 } 710 } 711 return true; 712 } 713 714 private boolean doParametersMatch(ServiceMethodParameter paramM6, ServiceMethodParameter paramM7) { 715 if (!paramM6.getName().equals(paramM7.getName())) { 716 return false; 717 } 718 if (!paramM6.getType().equals(paramM7.getType())) { 719 return false; 720 } 721 return true; 722 } 723 724 private ServiceMethod findMethod(ServiceMethod method1) { 725 ServiceMethod method2 = findMethod2(method1.getService(), method1.getName()); 726 if (method2 == null) { 727 String methodRename = knownMethodRenames.get(method1.getService() + "Service." + method1.getName()); 728 if (methodRename != null) { 729 method2 = findMethod2(method1.getService(), methodRename); 730 if (method2 == null) { 731 out.println("# (-) " + method1.getService() + "Service." + method1.getName() 732 + " could not be found even after being renamed to " + methodRename); 733 return null; 734 } 735 } 736 } 737 return method2; 738 } 739 740 private ServiceMethod findMethod2(String serviceKey, String methodName) { 741 ServiceMethod method2 = finderM7.findServiceMethod(serviceKey, methodName); 742 if (method2 == null) { 743 if (serviceKey.equals("Lu")) { 744 method2 = finderM7.findServiceMethod("Clu", methodName); 745 if (method2 == null) { 746 method2 = finderM7.findServiceMethod("Lui", methodName); 747 } 748 } 749 } 750 return method2; 751 } 752 753 private String calcMethods(ServiceMethod method1) { 754 StringBuilder bldr = new StringBuilder(); 755 String comma = ""; 756 for (ServiceMethod method2 : finderM7.findServiceMethods(method1.getService())) { 757 bldr.append(comma); 758 comma = ", "; 759 bldr.append(method2.getName()); 760 } 761 return bldr.toString(); 762 } 763 764 private String calcPossibleMethods(ServiceMethod method1) { 765 StringBuilder bldr = new StringBuilder(); 766 String comma = ""; 767 for (ServiceMethod method2 : findPossibleMethods(method1)) { 768 bldr.append(comma); 769 comma = ", "; 770 bldr.append(method2.getName()); 771 } 772 return bldr.toString(); 773 } 774 775 private List<ServiceMethod> findPossibleMethods(ServiceMethod method1) { 776 List<ServiceMethod> methods = new ArrayList<ServiceMethod>(); 777 List<ServiceMethod> wideNet = null; 778// if (method1.getService().equals("Lu")) { 779// wideNet = finderM7.findServiceMethods("Clu"); 780// wideNet.addAll(finderM7.findServiceMethods("Lui")); 781// } else { 782 wideNet = finderM7.findServiceMethods(method1.getService()); 783// } 784 for (ServiceMethod method2 : wideNet) { 785 if (isPossibleMatch(method1, method2)) { 786 methods.add(method2); 787 } 788 } 789 return methods; 790 } 791 792 private boolean isPossibleMatch(ServiceMethod method1, ServiceMethod method2) { 793 if (method1.getName().contains(method2.getName())) { 794 return true; 795 } 796 if (method2.getName().contains(method1.getName())) { 797 return true; 798 } 799 if (method1.getName().startsWith("get") && method2.getName().startsWith("get")) { 800 return true; 801 } 802 if (method1.getName().startsWith("add") && method2.getName().startsWith("create")) { 803 return true; 804 } 805 if (method1.getName().startsWith("create") && method2.getName().startsWith("create")) { 806 return true; 807 } 808 if (method1.getName().startsWith("update") && method2.getName().startsWith("update")) { 809 return true; 810 } 811 if (method1.getName().startsWith("delete") && method2.getName().startsWith("delete")) { 812 return true; 813 } 814 if (method1.getName().startsWith("remove") && method2.getName().startsWith("delete")) { 815 return true; 816 } 817 if (method1.getName().startsWith("validate") && method2.getName().startsWith("validate")) { 818 return true; 819 } 820 return false; 821 } 822}