/* * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.carbon.governance.comparator.wsdl; import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.governance.comparator.Comparison; import org.wso2.carbon.governance.comparator.ComparisonException; import org.wso2.carbon.governance.comparator.common.DefaultComparison; import org.wso2.carbon.governance.comparator.utils.ComparatorConstants; import org.wso2.carbon.governance.comparator.utils.WSDLComparisonUtils; import javax.wsdl.Definition; import javax.wsdl.Fault; import javax.wsdl.Input; import javax.wsdl.Operation; import javax.wsdl.Output; import javax.wsdl.PortType; import javax.wsdl.WSDLException; import javax.xml.namespace.QName; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; public class WSDLOperationComparator extends AbstractWSDLComparator { private final Log log = LogFactory.getLog(WSDLImportsComparator.class); @Override void compareInternal(Definition base, Definition changed, DefaultComparison comparison) throws ComparisonException { //Here we only compare operations belong to common PortTypes compareOperations(base, changed, comparison); } protected void compareOperations(Definition base, Definition changed, DefaultComparison comparison) { DefaultComparison.DefaultSection section = null; Set<QName> commonKeys = Sets.intersection(base.getPortTypes().keySet(), changed.getPortTypes().keySet()); List<Operation> additions = new ArrayList<>(); List<Operation> removeals = new ArrayList<>(); List<Operation> leftChanges = new ArrayList<>(); List<Operation> rightChanges = new ArrayList<>(); if (commonKeys.size() > 0) { for (QName portTypeName : commonKeys) { PortType leftPortType = base.getPortType(portTypeName); PortType rightPortType = changed.getPortType(portTypeName); List<Operation> leftOperations = leftPortType.getOperations(); List<Operation> rightOperations = rightPortType.getOperations(); for (Operation left : leftOperations) { Operation right = rightPortType.getOperation(left.getName(), null, null); if (right != null) { if (isDifferent(left, right)) { leftChanges.add(left); rightChanges.add(right); } rightOperations.remove(right); } else if (right == null) { removeals.add(left); } } additions = rightOperations; } } if (section == null && additions.size() > 0) { section = comparison.newSection(); } processAdditions(section, additions, changed); if (section == null && removeals.size() > 0) { section = comparison.newSection(); } processRemovals(section, removeals, base); boolean different = false; for (int i = 0; i < leftChanges.size(); i++) { if (isDifferent(leftChanges.get(i), rightChanges.get(i))) { different = true; break; } } if (section == null && different) { section = comparison.newSection(); } if (different) { processChanges(section, leftChanges, rightChanges, base, changed); } if (section != null) { comparison.addSection(ComparatorConstants.WSDL_OPERATIONS, section); } } protected void processAdditions(DefaultComparison.DefaultSection section, List<Operation> additions, Definition changed) { if (additions.size() > 0) { section.addSectionSummary(Comparison.SectionType.CONTENT_ADDITION, ComparatorConstants.NEW_OPERATIONS); DefaultComparison.DefaultSection.DefaultTextContent content = section.newTextContent(); content.setContent(getOperationOnly(additions, changed)); section.addContent(Comparison.SectionType.CONTENT_ADDITION, content); } } protected void processRemovals(DefaultComparison.DefaultSection section, List<Operation> removeals, Definition base) { if (removeals.size() > 0) { section.addSectionSummary(Comparison.SectionType.CONTENT_REMOVAL, ComparatorConstants.REMOVE_OPERATIONS); DefaultComparison.DefaultSection.DefaultTextContent content = section.newTextContent(); content.setContent(getOperationOnly(removeals, base)); section.addContent(Comparison.SectionType.CONTENT_REMOVAL, content); } } protected void processChanges(DefaultComparison.DefaultSection section, List<Operation> leftChanges, List<Operation> rightChanges, Definition base, Definition changed) { section.addSectionSummary(Comparison.SectionType.CONTENT_CHANGE, ComparatorConstants.CHANGED_OPERATIONS); DefaultComparison.DefaultSection.DefaultTextChangeContent content = section.newTextChangeContent(); DefaultComparison.DefaultSection.DefaultTextChange textChange = section.newTextChange(); textChange.setOriginal(getOperationOnly(leftChanges, base)); textChange.setChanged(getOperationOnly(rightChanges, changed)); content.setContent(textChange); section.addContent(Comparison.SectionType.CONTENT_CHANGE, content); } private String getOperationOnly(List<Operation> operations, Definition definition) { try { Definition tempDefinition = WSDLComparisonUtils.getWSDLDefinition(); PortType portType = tempDefinition.createPortType(); portType.setUndefined(false); portType.setQName(new QName(definition.getTargetNamespace(), "temp")); for (Operation operation : operations) { portType.addOperation(operation); } tempDefinition.addPortType(portType); WSDLComparisonUtils.copyNamespaces(definition, tempDefinition); String content = WSDLComparisonUtils.getWSDLWithoutDeclaration(tempDefinition); content = content.substring(content.indexOf(">") + 2); return content.replace("</wsdl:portType>", ""); } catch (WSDLException e) { log.error(e); } return null; } private boolean isDifferent(Operation left, Operation right) { if (isDifferent(left.getInput(), right.getInput())) { return true; } if (isDifferent(left.getOutput(), right.getOutput())) { return true; } if (isDifferent(left.getFaults(), right.getFaults())) { return true; } return false; } private boolean isDifferent(Map<String, Fault> left, Map<String, Fault> right) { if (left != null && right != null && left.size() != right.size()) { return true; } else { MapDifference<String, Fault> mapDiff = Maps.difference(left, right); if (!mapDiff.areEqual()) { return true; } else { for (String name : mapDiff.entriesInCommon().keySet()) { if (isDifferent(left.get(name), right.get(name))) { return true; } } } } return false; } private boolean isDifferent(Fault left, Fault right) { if (left != null && right == null) { return true; } else if (right != null && left == null) { } else { if (left.getName() != null && right.getName() != null && !left.getName().equals(right.getName())) { return true; } if (left.getMessage() != null && right.getMessage() != null && WSDLComparisonUtils.isDiffrentMessages(left.getMessage(), right.getMessage())) { return true; } } return false; } private boolean isDifferent(Output left, Output right) { if (left == null && right == null) { return false; } else if (left != null && right == null) { return true; } else if (right != null && left == null) { return true; } else { if (left.getName() != null && right.getName() != null && !left.getName().equals(right.getName())) { return true; } if (left.getMessage() != null && right.getMessage() != null && WSDLComparisonUtils.isDiffrentMessages(left.getMessage(), right.getMessage())) { return true; } } return false; } private boolean isDifferent(Input left, Input right) { if (left != null && right == null) { return true; } else if (right != null && left == null) { return true; } else { if (left.getName() != null && right.getName() != null && !left.getName().equals(right.getName())) { return true; } if (left.getMessage() != null && right.getMessage() != null && WSDLComparisonUtils.isDiffrentMessages(left.getMessage(), right.getMessage())) { return true; } } return false; } }