1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.vc.test;
17
18 import com.predic8.schema.ComplexType;
19 import com.predic8.schema.Sequence;
20 import com.predic8.soamodel.Difference;
21 import com.predic8.wsdl.Definitions;
22 import com.predic8.wsdl.Operation;
23 import com.predic8.wsdl.PortType;
24 import com.predic8.wsdl.WSDLParser;
25 import com.predic8.wsdl.diff.WsdlDiffGenerator;
26 import org.apache.commons.collections.CollectionUtils;
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.log4j.Logger;
29 import org.codehaus.jackson.JsonNode;
30 import org.codehaus.jackson.map.ObjectMapper;
31 import org.kuali.rice.core.api.config.property.Config;
32 import org.kuali.rice.core.api.config.property.ConfigContext;
33 import org.kuali.rice.core.api.lifecycle.BaseLifecycle;
34 import org.kuali.rice.core.api.lifecycle.Lifecycle;
35 import org.kuali.rice.core.framework.resourceloader.SpringResourceLoader;
36 import org.kuali.rice.test.BaselineTestCase;
37
38 import javax.xml.namespace.QName;
39 import java.io.BufferedReader;
40 import java.io.File;
41 import java.io.IOException;
42 import java.io.InputStreamReader;
43 import java.net.MalformedURLException;
44 import java.net.URL;
45 import java.util.*;
46 import java.util.regex.Pattern;
47
48 import static org.junit.Assert.assertTrue;
49 import static org.junit.Assert.fail;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.ROLLBACK)
75 public abstract class WsdlCompareTestCase extends BaselineTestCase {
76 private static final Logger LOG = Logger.getLogger(WsdlCompareTestCase.class);
77 private static final String WSDL_URL = "wsdl.test.previous.url";
78 private static final String WSDL_PREVIOUS_VERSION = "wsdl.test.previous.version";
79 private static final String LINE_SEPARATOR = System.getProperty("line.separator");
80
81 private String previousVersion;
82
83 private static final List<String> ignoreBreakageRegexps = Arrays.asList(
84 ".*Position of any changed from .*",
85 ".*Position of element null changed.$",
86 " *ComplexType [^ ]* removed.$",
87
88 " *Element [^ ]* removed.$",
89 " *SimpleType [^ ]* removed.$"
90 );
91
92 public WsdlCompareTestCase(String moduleName) {
93 super(moduleName);
94 }
95
96 protected List<String> verifyWsdlDifferences(Difference diff, String level) {
97 List<String> results = new ArrayList<String>();
98
99 if (diff.isBreaks() == true) {
100 boolean ignore = false;
101 for (String ignoreBreakageRegexp : ignoreBreakageRegexps) {
102 if (diff.getDescription().matches(ignoreBreakageRegexp)) {
103 ignore = true;
104 break;
105 }
106 }
107
108 if (ignore) {
109 LOG.info(level + "non-breaking change: " + diff.getDescription());
110 } else {
111 LOG.error(level + "breaking change: " + diff.getType() + diff.getDescription());
112 results.add(level + diff.getDescription());
113 }
114 } else {
115 LOG.trace(level + "trivial change: " + diff.getDescription());
116 }
117
118
119 String opBreakageString = checkForOperationBasedChanges(diff);
120 if (opBreakageString != null) {
121 results.add(level + opBreakageString);
122 }
123
124
125 String returnTypeBreakageString = checkForFormerlyVoidResponse(diff);
126 if (returnTypeBreakageString != null) {
127 results.add(level + returnTypeBreakageString);
128 }
129
130 for (Difference moreDiff : diff.getDiffs()) {
131 List<String> childBreakages = verifyWsdlDifferences(moreDiff, level + " ");
132 for (String childBreakage : childBreakages) {
133 if (!diff.getDescription().trim().startsWith("Schema ")) {
134 results.add(level + diff.getDescription() + LINE_SEPARATOR + childBreakage);
135 } else {
136 results.add(childBreakage);
137 }
138 }
139 }
140
141 return results;
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155 private String checkForOperationBasedChanges(Difference diff) {
156 if ("sequence".equals(diff.getType())
157 && diff.getA() != null
158 && diff.getB() != null) {
159 Sequence oldSequence = (Sequence)diff.getA();
160 Sequence newSequence = (Sequence)diff.getB();
161 if (newSequence.getParent() instanceof ComplexType) {
162 ComplexType parent = (ComplexType)newSequence.getParent();
163 String serviceName = newSequence.getSchema().getDefinitions().getName();
164 PortType portType = newSequence.getSchema().getDefinitions().getPortType(serviceName);
165 if (portType != null) {
166 Operation operation = portType.getOperation(parent.getName());
167
168 if (operation != null) {
169 return "Element cannot be added to a sequence if sequence is an Operation " +
170 diff.getDescription();
171 }
172
173
174 }
175 }
176 }
177 return null;
178 }
179
180
181
182
183
184
185
186
187
188
189
190 private String checkForFormerlyVoidResponse(Difference diff) {
191
192
193 if ( ! "sequence".equals(diff.getType()) || diff.getA() == null || diff.getB() == null) {
194 return null;
195 }
196
197 Sequence oldSequence = (Sequence)diff.getA();
198 Sequence newSequence = (Sequence)diff.getB();
199
200 if ( ! (newSequence.getParent() instanceof ComplexType)) {
201 return null;
202 }
203
204 ComplexType parent = (ComplexType)newSequence.getParent();
205
206
207 if ( ! parent.getName().endsWith("Response")) {
208 return null;
209 }
210
211
212 if (CollectionUtils.isEmpty(oldSequence.getElements()) &&
213 CollectionUtils.isNotEmpty(newSequence.getElements())) {
214 return "Element cannot be added to a previously empty return";
215 }
216
217 return null;
218 }
219
220 protected List<Difference> compareWsdlDefinitions(String oldWsdl, String newWsdl) {
221 WSDLParser parser = new WSDLParser();
222
223 Definitions wsdl1;
224 Definitions wsdl2;
225 try {
226 wsdl1 = parser.parse(oldWsdl);
227 } catch (com.predic8.xml.util.ResourceDownloadException e) {
228 LOG.info("Couldn't download " + oldWsdl + ", maybe the service didn't exist in this version?");
229 return Collections.emptyList();
230 }
231 try {
232 wsdl2 = parser.parse(newWsdl);
233 } catch (com.predic8.xml.util.ResourceDownloadException e) {
234 LOG.info("Couldn't download" + newWsdl + ", maybe the service didn't exist in this version?");
235 return Collections.emptyList();
236 }
237
238 WsdlDiffGenerator diffGen = new WsdlDiffGenerator(wsdl1, wsdl2);
239 return diffGen.compare();
240 }
241
242 protected String getPreviousVersionWsdlUrl(String wsdlFile, MavenVersion previousVersion) {
243
244 StringBuilder oldWsdl = new StringBuilder(buildWsdlUrlPrefix(previousVersion.getOriginalForm()));
245 oldWsdl.append("rice-");
246 oldWsdl.append(getModuleName());
247 oldWsdl.append("-api-");
248 oldWsdl.append(previousVersion.getOriginalForm());
249 oldWsdl.append("-");
250 oldWsdl.append(wsdlFile);
251
252 return oldWsdl.toString();
253 }
254
255
256 private String buildWsdlUrlPrefix(String previousVersion) {
257 String wsdlUrl = ConfigContext.getCurrentContextConfig().getProperty(WSDL_URL);
258
259 if (StringUtils.isNotBlank(wsdlUrl)
260 && StringUtils.isNotBlank(previousVersion)) {
261 StringBuilder urlBuilder = new StringBuilder(wsdlUrl);
262 if (!wsdlUrl.endsWith("/")) {
263 urlBuilder.append("/");
264 }
265 urlBuilder.append("rice-");
266 urlBuilder.append(getModuleName());
267 urlBuilder.append("-api/");
268 urlBuilder.append(previousVersion);
269 urlBuilder.append("/");
270
271 return urlBuilder.toString();
272
273 } else {
274 throw new RuntimeException("Couldn't build wsdl url prefix");
275 }
276 }
277
278
279
280
281
282
283
284
285 protected Map<String, List<VersionTransition>> getWsdlVersionTransitionBlacklists() {
286 return new HashMap<String, List<VersionTransition>>();
287 }
288
289 protected void compareWsdlFiles(File[] wsdlFiles) {
290 List<VersionCompatibilityBreakage> breakages = new ArrayList<VersionCompatibilityBreakage>();
291
292 assertTrue("There should be wsdls to compare", wsdlFiles != null && wsdlFiles.length > 0);
293
294 MavenVersion previousVersion = new MavenVersion(getPreviousVersion(),
295 "0" );
296 MavenVersion currentVersion = getCurrentMavenVersion();
297 List<MavenVersion> versions = getVersionRange(previousVersion, currentVersion);
298 List<VersionTransition> transitions = generateVersionTransitions(currentVersion, versions);
299
300 for (File wsdlFile : wsdlFiles) {
301 if (wsdlFile.getName().endsWith(".wsdl")) {
302 LOG.info("TESTING WSDL: " + wsdlFile.getAbsolutePath());
303 String newWsdl = wsdlFile.getAbsolutePath();
304
305
306 List<VersionTransition> wsdlTransitionBlacklist =
307 getWsdlVersionTransitionBlacklists().get(getServiceNameFromWsdlFile(wsdlFile));
308
309 if (wsdlTransitionBlacklist == null) { wsdlTransitionBlacklist = Collections.emptyList(); }
310
311 for (VersionTransition transition : transitions) if (!wsdlTransitionBlacklist.contains(transition)) {
312 breakages.addAll(testWsdlVersionTransition(currentVersion, wsdlFile, transition));
313 } else {
314 LOG.info("Ignoring blacklisted " + transition);
315 }
316 }
317 }
318
319 if (!breakages.isEmpty()) {
320 fail(buildBreakagesSummary(breakages));
321 }
322 }
323
324
325 String getServiceNameFromWsdlFile(File wsdlFile) {
326 String fileName = wsdlFile.getName();
327 int beginIndex = 1 + fileName.lastIndexOf('-');
328 int endIndex = fileName.lastIndexOf('.');
329
330 return fileName.substring(beginIndex, endIndex);
331 }
332
333
334
335
336
337
338
339
340 private List<VersionCompatibilityBreakage> testWsdlVersionTransition(MavenVersion currentVersion, File wsdlFile, VersionTransition transition) {
341 List<VersionCompatibilityBreakage> breakages = new ArrayList<VersionCompatibilityBreakage>();
342
343 String fromVersionWsdlUrl = getPreviousVersionWsdlUrl(wsdlFile.getName(), transition.getFromVersion());
344 String toVersionWsdlUrl = getPreviousVersionWsdlUrl(wsdlFile.getName(), transition.getToVersion());
345
346
347 if (transition.getToVersion().equals(currentVersion)) {
348 toVersionWsdlUrl = wsdlFile.getAbsolutePath();
349 }
350
351 getPreviousVersionWsdlUrl(wsdlFile.getName(), transition.getToVersion());
352
353 LOG.info("checking " + transition);
354
355 if (fromVersionWsdlUrl == null) {
356 LOG.warn("SKIPPING check, wsdl not found for " + fromVersionWsdlUrl);
357 } else if (toVersionWsdlUrl == null) {
358 LOG.warn("SKIPPING check, wsdl not found for " + toVersionWsdlUrl);
359 } else {
360 List<Difference> differences = compareWsdlDefinitions(fromVersionWsdlUrl, toVersionWsdlUrl);
361 for (Difference diff : differences) {
362 List<String> breakageStrings = verifyWsdlDifferences(diff, "");
363
364 for (String breakage : breakageStrings) {
365 breakages.add(new VersionCompatibilityBreakage(
366 transition.fromVersion, transition.toVersion,
367 fromVersionWsdlUrl, toVersionWsdlUrl, breakage));
368 }
369 }
370 }
371
372 return breakages;
373 }
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409 protected List<VersionTransition> generateVersionTransitions(MavenVersion currentVersion, List<MavenVersion> versions) {
410 List<VersionTransition> results = new ArrayList<VersionTransition>();
411
412 versions = new ArrayList<MavenVersion>(versions);
413 Collections.sort(versions, mavenVersionTimestampComparator);
414
415
416 Collections.reverse(versions);
417
418 final MavenVersion currentMinorVersion = trimToMinorVersion(currentVersion);
419 MavenVersion buildingTransitionsTo = currentVersion;
420
421
422
423 Set<MavenVersion> minorVersionsFrom = new HashSet<MavenVersion>();
424
425 for (MavenVersion version : versions) if (version.compareTo(buildingTransitionsTo) < 0) {
426 MavenVersion minorVersion = trimToMinorVersion(version);
427 if (minorVersion.equals(currentMinorVersion)) {
428
429 results.add(new VersionTransition(version, buildingTransitionsTo));
430 buildingTransitionsTo = version;
431
432
433 minorVersionsFrom.clear();
434 } else if (!minorVersionsFrom.contains(minorVersion)) {
435 results.add(new VersionTransition(version, buildingTransitionsTo));
436 minorVersionsFrom.add(minorVersion);
437 }
438 }
439
440
441 Collections.reverse(results);
442
443 return results;
444 }
445
446
447
448
449 private MavenVersion trimToMinorVersion(MavenVersion fullVersion) {
450 return new MavenVersion(""+fullVersion.getNumbers().get(0)+"."+fullVersion.getNumbers().get(1), "0");
451 }
452
453 protected String buildBreakagesSummary(List<VersionCompatibilityBreakage> breakages) {
454 StringBuilder errorsStringBuilder =
455 new StringBuilder(LINE_SEPARATOR + "!!!!! Detected " + breakages.size() + " VC Breakages !!!!!"
456 + LINE_SEPARATOR);
457
458 MavenVersion lastOldVersion = null;
459 String lastOldWsdlUrl = "";
460
461 for (VersionCompatibilityBreakage breakage : breakages) {
462
463 if (lastOldVersion != breakage.oldMavenVersion || lastOldWsdlUrl != breakage.oldWsdlUrl) {
464 lastOldVersion = breakage.oldMavenVersion;
465 lastOldWsdlUrl = breakage.oldWsdlUrl;
466
467 errorsStringBuilder.append(LINE_SEPARATOR + "Old Version: " + lastOldVersion.getOriginalForm()
468 +", wsdl: " + lastOldWsdlUrl);
469 errorsStringBuilder.append(LINE_SEPARATOR + "New Version: " + breakage.newMavenVersion.getOriginalForm()
470 +", wsdl: " + breakage.newWsdlUrl + LINE_SEPARATOR + LINE_SEPARATOR);
471 }
472 errorsStringBuilder.append(breakage.breakageMessage + LINE_SEPARATOR);
473 }
474 return errorsStringBuilder.toString();
475 }
476
477 public String getPreviousVersion() {
478 if (StringUtils.isEmpty(this.previousVersion)) {
479 this.previousVersion = ConfigContext.getCurrentContextConfig().getProperty(WSDL_PREVIOUS_VERSION);
480 }
481 return this.previousVersion;
482 }
483
484 public void setPreviousVersion(String previousVersion) {
485 this.previousVersion = previousVersion;
486 }
487
488 @Override
489 protected Lifecycle getLoadApplicationLifecycle() {
490 SpringResourceLoader springResourceLoader = new SpringResourceLoader(new QName("VCTestHarnessResourceLoader"), "classpath:VCTestHarnessSpringBeans.xml", null);
491 springResourceLoader.setParentSpringResourceLoader(getTestHarnessSpringResourceLoader());
492 return springResourceLoader;
493 }
494
495 @Override
496 protected List<Lifecycle> getPerTestLifecycles() {
497 return new ArrayList<Lifecycle>();
498 }
499
500 @Override
501 protected List<Lifecycle> getSuiteLifecycles() {
502 List<Lifecycle> lifecycles = new LinkedList<Lifecycle>();
503
504
505
506
507 lifecycles.add(new BaseLifecycle() {
508 @Override
509 public void start() throws Exception {
510 Config config = getTestHarnessConfig();
511 ConfigContext.init(config);
512 super.start();
513 }
514 });
515
516 return lifecycles;
517 }
518
519
520
521
522
523
524
525
526
527 protected List<MavenVersion> getVersionRange(MavenVersion lowestVersion, MavenVersion highestVersion) {
528 ArrayList<MavenVersion> results = new ArrayList<MavenVersion>();
529
530 if (highestVersion.compareTo(lowestVersion) <= 0) {
531 throw new IllegalStateException("currentVersion " + highestVersion +
532 " is <= previousVersion " + lowestVersion);
533 }
534 List<MavenVersion> riceVersions = getRiceMavenVersions();
535
536 for (MavenVersion riceVersion : riceVersions) {
537 if ( highestVersion.compareTo(riceVersion) > 0 &&
538 lowestVersion.compareTo(riceVersion) <= 0 &&
539 "".equals(riceVersion.getQualifier()) ) {
540 results.add(riceVersion);
541 }
542 }
543
544 return results;
545 }
546
547
548
549 private static List<MavenVersion> riceMavenVersions = null;
550
551 private static List<MavenVersion> getRiceMavenVersions() {
552 if (riceMavenVersions == null) {
553 String searchContent = getMavenSearchResults();
554 riceMavenVersions = parseSearchResults(searchContent);
555
556 Collections.sort(riceMavenVersions, mavenVersionTimestampComparator);
557
558 LOG.info("Published versions, sorted by timestamp:");
559 for (MavenVersion riceVersion : riceMavenVersions) {
560 LOG.info("" + riceVersion.getTimestamp() + " " + riceVersion.getOriginalForm());
561 }
562
563 }
564 return riceMavenVersions;
565 }
566
567
568
569
570 private MavenVersion getCurrentMavenVersion() {
571 return new MavenVersion(ConfigContext.getCurrentContextConfig().getProperty("rice.version"),
572 ""+System.currentTimeMillis());
573 }
574
575 private static List<MavenVersion> parseSearchResults(String searchContent) {
576 LinkedList<MavenVersion> riceVersions = new LinkedList<MavenVersion>();
577
578 ObjectMapper mapper = new ObjectMapper();
579 JsonNode rootNode;
580 try {
581 rootNode = mapper.readTree(searchContent);
582 } catch (IOException e) {
583 throw new RuntimeException("Can't parse maven search results", e);
584 }
585 JsonNode docsNode = rootNode.get("response").get("docs");
586
587 for (JsonNode node : docsNode) {
588 String versionStr = node.get("v").toString();
589 String timestampStr = node.get("timestamp").toString();
590
591 riceVersions.add(new MavenVersion(versionStr.replace( "\"",""), timestampStr));
592 }
593
594 Collections.sort(riceVersions);
595 return riceVersions;
596 }
597
598 private static String getMavenSearchResults() {
599
600
601 final String mavenSearchUrlString =
602 "http://search.maven.org/solrsearch/select?q=g:%22org.kuali.rice%22+AND+a:%22rice%22&core=gav&rows=20&wt=json";
603
604 URL mavenSearchUrl;
605
606 try {
607 mavenSearchUrl = new URL(mavenSearchUrlString);
608 } catch (MalformedURLException e) {
609 throw new RuntimeException("can't parse maven search url", e);
610 }
611
612 StringBuilder contentBuilder = new StringBuilder();
613 BufferedReader contentReader;
614 try {
615 contentReader = new BufferedReader(new InputStreamReader(mavenSearchUrl.openStream()));
616 String line;
617 while (null != (line = contentReader.readLine())) {
618 contentBuilder.append(line + LINE_SEPARATOR);
619 }
620 } catch (IOException e) {
621 throw new RuntimeException("Unable to read search results", e);
622 }
623 return contentBuilder.toString();
624 }
625
626
627
628
629 protected static class MavenVersion implements Comparable<MavenVersion> {
630 private static final Pattern PERIOD_PATTERN = Pattern.compile("\\.");
631 private final List<Integer> numbers;
632 private final String originalForm;
633 private final String qualifier;
634 private final Long timestamp;
635
636
637
638
639
640 public MavenVersion(String versionString) {
641 this(versionString, "0");
642 }
643
644 public MavenVersion(String versionString, String timestampString) {
645 originalForm = versionString;
646 if (versionString == null || "".equals(versionString.trim())) {
647 throw new IllegalArgumentException("empty or null version string");
648 }
649 String versionPart;
650 int dashIndex = versionString.indexOf('-');
651 if (dashIndex != -1 && versionString.length()-1 > dashIndex) {
652 qualifier = versionString.substring(dashIndex+1).trim();
653 versionPart = versionString.substring(0,dashIndex);
654 } else {
655 versionPart = versionString;
656 qualifier = "";
657 }
658 String [] versionArray = PERIOD_PATTERN.split(versionPart);
659
660 List<Integer> numbersBuilder = new ArrayList<Integer>(versionArray.length);
661
662 for (String versionParticle : versionArray) {
663 numbersBuilder.add(Integer.valueOf(versionParticle));
664 }
665
666 numbers = Collections.unmodifiableList(numbersBuilder);
667
668 timestamp = Long.valueOf(timestampString);
669 }
670
671 @Override
672 public int compareTo(MavenVersion that) {
673 Iterator<Integer> thisNumbersIter = this.numbers.iterator();
674 Iterator<Integer> thatNumbersIter = that.numbers.iterator();
675
676 while (thisNumbersIter.hasNext()) {
677
678 if (!thatNumbersIter.hasNext()) return 1;
679
680 int numberComparison = thisNumbersIter.next().compareTo(thatNumbersIter.next());
681
682
683 if (numberComparison != 0) return numberComparison;
684 }
685
686 if (thatNumbersIter.hasNext()) return -1;
687
688 return compareQualifiers(this.qualifier, that.qualifier);
689 }
690
691 private static int compareQualifiers(String thisQ, String thatQ) {
692
693 if ("".equals(thisQ)) {
694 if ("".equals(thatQ)) {
695 return 0;
696 }
697 return 1;
698 } else if ("".equals(thatQ)) {
699 return -1;
700 }
701
702 return thisQ.compareTo(thatQ);
703 }
704
705 public List<Integer> getNumbers() {
706 return Collections.unmodifiableList(numbers);
707 }
708
709 public String getQualifier() {
710 return qualifier;
711 }
712
713 public Long getTimestamp() {
714 return timestamp;
715 }
716
717 public String getOriginalForm() {
718 return originalForm;
719 }
720
721 @Override
722 public String toString() {
723 return "MavenVersion{" +
724 originalForm +
725 '}';
726 }
727
728 @Override
729 public boolean equals(Object o) {
730 if (this == o) {
731 return true;
732 }
733 if (o == null || getClass() != o.getClass()) {
734 return false;
735 }
736
737 final MavenVersion that = (MavenVersion) o;
738
739 if (!originalForm.equals(that.originalForm)) {
740 return false;
741 }
742
743 return true;
744 }
745
746 @Override
747 public int hashCode() {
748 return originalForm.hashCode();
749 }
750 }
751
752
753
754
755 private static final Comparator<MavenVersion> mavenVersionTimestampComparator = new Comparator<MavenVersion>() {
756 @Override
757 public int compare(MavenVersion o1, MavenVersion o2) {
758 return o1.getTimestamp().compareTo(o2.getTimestamp());
759 }
760 };
761
762
763
764
765 public static class VersionTransition {
766 private final MavenVersion fromVersion;
767 private final MavenVersion toVersion;
768
769 public VersionTransition(MavenVersion fromVersion, MavenVersion toVersion) {
770 this.fromVersion = fromVersion;
771 this.toVersion = toVersion;
772 if (fromVersion == null) throw new IllegalArgumentException("fromVersion must not be null");
773 if (toVersion == null) throw new IllegalArgumentException("toVersion must not be null");
774 }
775
776 public VersionTransition(String fromVersion, String toVersion) {
777 this(new MavenVersion(fromVersion), new MavenVersion(toVersion));
778 }
779
780 private MavenVersion getFromVersion() {
781 return fromVersion;
782 }
783
784 private MavenVersion getToVersion() {
785 return toVersion;
786 }
787
788 @Override
789 public boolean equals(Object o) {
790 if (this == o) return true;
791 if (o == null || getClass() != o.getClass()) return false;
792
793 VersionTransition that = (VersionTransition) o;
794
795 if (!fromVersion.equals(that.fromVersion)) return false;
796 if (!toVersion.equals(that.toVersion)) return false;
797
798 return true;
799 }
800
801 @Override
802 public int hashCode() {
803 int result = fromVersion.hashCode();
804 result = 31 * result + toVersion.hashCode();
805 return result;
806 }
807
808 @Override
809 public String toString() {
810 return "VersionTransition{" +
811 fromVersion.getOriginalForm() +
812 " -> " + toVersion.getOriginalForm() +
813 '}';
814 }
815 }
816
817
818
819
820 protected static class VersionCompatibilityBreakage {
821 private final MavenVersion oldMavenVersion;
822 private final MavenVersion newMavenVersion;
823 private final String oldWsdlUrl;
824 private final String newWsdlUrl;
825 private final String breakageMessage;
826
827 public VersionCompatibilityBreakage(MavenVersion oldMavenVersion, MavenVersion newMavenVersion, String oldWsdlUrl, String newWsdlUrl, String breakageMessage) {
828 if (oldMavenVersion == null) throw new IllegalArgumentException("oldMavenVersion must not be null");
829 if (newMavenVersion == null) throw new IllegalArgumentException("newMavenVersion must not be null");
830 if (StringUtils.isEmpty(oldWsdlUrl)) throw new IllegalArgumentException("oldWsdlUrl must not be empty/null");
831 if (StringUtils.isEmpty(newWsdlUrl)) throw new IllegalArgumentException("newWsdlUrl must not be empty/null");
832 if (StringUtils.isEmpty(breakageMessage)) throw new IllegalArgumentException("breakageMessage must not be empty/null");
833 this.oldWsdlUrl = oldWsdlUrl;
834 this.newWsdlUrl = newWsdlUrl;
835 this.oldMavenVersion = oldMavenVersion;
836 this.newMavenVersion = newMavenVersion;
837 this.breakageMessage = breakageMessage;
838 }
839
840 @Override
841 public String toString() {
842 return "VersionCompatibilityBreakage{" +
843 "oldMavenVersion=" + oldMavenVersion +
844 ", newMavenVersion=" + newMavenVersion +
845 ", oldWsdlUrl='" + oldWsdlUrl + '\'' +
846 ", newWsdlUrl='" + newWsdlUrl + '\'' +
847 ", breakageMessage='" + breakageMessage + '\'' +
848 '}';
849 }
850 }
851
852 }