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