/* * Copyright 2014 JBoss Inc * * Licensed 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.artificer.common; import org.artificer.common.error.ArtificerConflictException; import org.artificer.common.error.ArtificerWrongModelException; import org.artificer.common.visitors.HierarchicalArtifactVisitor; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Actor; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ActorEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ActorTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Artifact; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.AttributeDeclaration; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Binding; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperation; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationFault; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationFaultEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationFaultTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationInput; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationInputEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationInputTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationOutput; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationOutputEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationOutputTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingOperationTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BindingTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Choreography; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ChoreographyProcess; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ClassificationData; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Collaboration; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.CollaborationProcess; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ComplexTypeDeclaration; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Composition; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DerivedArtifactEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DerivedArtifactTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DerivedArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Document; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DocumentArtifactEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DocumentArtifactTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DocumentArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Effect; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.EffectEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.EffectTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Element; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ElementDeclaration; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ElementDeclarationEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ElementDeclarationTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ElementEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ElementTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Error; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ErrorResponse; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Event; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.EventEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.EventTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ExtendedArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ExtendedDocument; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ExtensionType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Fault; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.FaultEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.FaultTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.InformationType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.InformationTypeEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.InformationTypeTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Message; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.MessageEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.MessageTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.NamedWsdlDerivedArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ObjectFactory; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Operation; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationInput; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationInputEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationInputTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationOutput; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationOutputEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationOutputTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OperationTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Orchestration; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OrchestrationEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OrchestrationProcess; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OrchestrationProcessEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OrchestrationProcessTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.OrchestrationTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Organization; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Part; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PartEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PartTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Policy; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyAttachment; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyDocument; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyExpression; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyExpressionEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyExpressionTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicySubject; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicySubjectEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicySubjectTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PolicyTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Port; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PortEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PortTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PortType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PortTypeEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PortTypeTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Process; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Property; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.PropertyData; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Relationship; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.RelationshipData; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.RelationshipTypeData; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Service; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceComposition; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceContract; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceContractEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceContractTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceEndpoint; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceImplementationModelEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceImplementationModelTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceImplementationModelType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInstance; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInstanceEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInstanceTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInterface; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInterfaceEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceInterfaceTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceOperation; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceOperationEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceOperationTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ServiceTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.SimpleTypeDeclaration; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.SoaModelType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.SoapAddress; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.SoapBinding; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.StoredQuery; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.StoredQueryData; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.System; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Target; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Task; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.TaskEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.TaskTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDerivedArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDocument; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDocumentEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlDocumentTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlExtension; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlExtensionEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlExtensionTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.WsdlService; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XmlDocument; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocument; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocumentEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocumentTarget; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdTypeEnum; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdTypeTarget; import org.reflections.ReflectionUtils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; /** * This visitor verifies numerous logical and spec-required constraints on artifact creations and updates. * * @author Brett Meyer */ public class ArtifactVerifier extends HierarchicalArtifactVisitor { private static final Set<String> reservedNames = new HashSet<String>(); private final ArtifactType artifactType; private BaseArtifactType oldArtifact = null; static { // TODO: This is not working reliably -- works well in EAP, but fails in WildFly (different module system, // etc.). For now, just hard-code the classes. // Reflections reflections = new Reflections(new ConfigurationBuilder() // .setScanners(new SubTypesScanner(false)) // .setUrls(ClasspathHelper.forClassLoader(ArtifactVerifier.class.getClassLoader())) // .filterInputsBy(new FilterBuilder().include( // FilterBuilder.prefix("org.oasis_open.docs.s_ramp.ns.s_ramp_v1")))); // Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class); Class[] classes = new Class[] { Actor.class, ActorEnum.class, ActorTarget.class, Artifact.class, AttributeDeclaration.class, BaseArtifactEnum.class, BaseArtifactTarget.class, BaseArtifactType.class, Binding.class, BindingEnum.class, BindingOperation.class, BindingOperationEnum.class, BindingOperationFault.class, BindingOperationFaultEnum.class, BindingOperationFaultTarget.class, BindingOperationInput.class, BindingOperationInputEnum.class, BindingOperationInputTarget.class, BindingOperationOutput.class, BindingOperationOutputEnum.class, BindingOperationOutputTarget.class, BindingOperationTarget.class, BindingTarget.class, Choreography.class, ChoreographyProcess.class, ClassificationData.class, Collaboration.class, CollaborationProcess.class, ComplexTypeDeclaration.class, Composition.class, DerivedArtifactEnum.class, DerivedArtifactTarget.class, DerivedArtifactType.class, Document.class, DocumentArtifactEnum.class, DocumentArtifactTarget.class, DocumentArtifactType.class, Effect.class, EffectEnum.class, EffectTarget.class, Element.class, ElementDeclaration.class, ElementDeclarationEnum.class, ElementDeclarationTarget.class, ElementEnum.class, ElementTarget.class, Error.class, ErrorResponse.class, Event.class, EventEnum.class, EventTarget.class, ExtendedArtifactType.class, ExtendedDocument.class, ExtensionType.class, Fault.class, FaultEnum.class, FaultTarget.class, InformationType.class, InformationTypeEnum.class, InformationTypeTarget.class, Message.class, MessageEnum.class, MessageTarget.class, NamedWsdlDerivedArtifactType.class, ObjectFactory.class, Operation.class, OperationEnum.class, OperationInput.class, OperationInputEnum.class, OperationInputTarget.class, OperationOutput.class, OperationOutputEnum.class, OperationOutputTarget.class, OperationTarget.class, Orchestration.class, OrchestrationEnum.class, OrchestrationProcess.class, OrchestrationProcessEnum.class, OrchestrationProcessTarget.class, OrchestrationTarget.class, Organization.class, Part.class, PartEnum.class, PartTarget.class, Policy.class, PolicyAttachment.class, PolicyDocument.class, PolicyEnum.class, PolicyExpression.class, PolicyExpressionEnum.class, PolicyExpressionTarget.class, PolicySubject.class, PolicySubjectEnum.class, PolicySubjectTarget.class, PolicyTarget.class, Port.class, PortEnum.class, PortTarget.class, PortType.class, PortTypeEnum.class, PortTypeTarget.class, Process.class, Property.class, PropertyData.class, Relationship.class, RelationshipData.class, RelationshipTypeData.class, Service.class, ServiceComposition.class, ServiceContract.class, ServiceContractEnum.class, ServiceContractTarget.class, ServiceEndpoint.class, ServiceEnum.class, ServiceImplementationModelEnum.class, ServiceImplementationModelTarget.class, ServiceImplementationModelType.class, ServiceInstance.class, ServiceInstanceEnum.class, ServiceInstanceTarget.class, ServiceInterface.class, ServiceInterfaceEnum.class, ServiceInterfaceTarget.class, ServiceOperation.class, ServiceOperationEnum.class, ServiceOperationTarget.class, ServiceTarget.class, SimpleTypeDeclaration.class, SoaModelType.class, SoapAddress.class, SoapBinding.class, StoredQuery.class, StoredQueryData.class, System.class, Target.class, Task.class, TaskEnum.class, TaskTarget.class, WsdlDerivedArtifactType.class, WsdlDocument.class, WsdlDocumentEnum.class, WsdlDocumentTarget.class, WsdlExtension.class, WsdlExtensionEnum.class, WsdlExtensionTarget.class, WsdlService.class, XmlDocument.class, XsdDocument.class, XsdDocumentEnum.class, XsdDocumentTarget.class, XsdType.class, XsdTypeEnum.class, XsdTypeTarget.class }; for (Class clazz : classes) { Set<Field> fields = ReflectionUtils.getAllFields(clazz); for (Field field : fields) { reservedNames.add(field.getName().toLowerCase()); } } } public ArtifactVerifier(ArtifactType artifactType) { this.artifactType = artifactType; } public ArtifactVerifier(BaseArtifactType oldArtifact, ArtifactType artifactType) { this(artifactType); this.oldArtifact = oldArtifact; } @Override protected void visitBase(BaseArtifactType artifact) { super.visitBase(artifact); verifyModel(artifact); verifyNames(artifact); } @Override public void visit(XsdDocument artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("importedXsds", artifact.getImportedXsds()); verifyEmptyDerivedRelationships("includedXsds", artifact.getIncludedXsds()); verifyEmptyDerivedRelationships("redefinedXsds", artifact.getRedefinedXsds()); } else { XsdDocument castOld = (XsdDocument) oldArtifact; verifyUnchangedDerivedRelationships("importedXsds", artifact.getImportedXsds(), castOld.getImportedXsds()); verifyUnchangedDerivedRelationships("includedXsds", artifact.getIncludedXsds(), castOld.getIncludedXsds()); verifyUnchangedDerivedRelationships("redefinedXsds", artifact.getRedefinedXsds(), castOld.getRedefinedXsds()); } } @Override public void visit(WsdlDocument artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("importedXsds", artifact.getImportedXsds()); verifyEmptyDerivedRelationships("includedXsds", artifact.getIncludedXsds()); verifyEmptyDerivedRelationships("redefinedXsds", artifact.getRedefinedXsds()); verifyEmptyDerivedRelationships("importedWsdls", artifact.getImportedWsdls()); } else { WsdlDocument castOld = (WsdlDocument) oldArtifact; verifyUnchangedDerivedRelationships("importedXsds", artifact.getImportedXsds(), castOld.getImportedXsds()); verifyUnchangedDerivedRelationships("includedXsds", artifact.getIncludedXsds(), castOld.getIncludedXsds()); verifyUnchangedDerivedRelationships("redefinedXsds", artifact.getRedefinedXsds(), castOld.getRedefinedXsds()); verifyUnchangedDerivedRelationships("importedWsdls", artifact.getImportedWsdls(), castOld.getImportedWsdls()); } } @Override public void visit(Message artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("part", artifact.getPart()); } else { Message castOld = (Message) oldArtifact; verifyUnchangedDerivedRelationships("part", artifact.getPart(), castOld.getPart()); } } @Override public void visit(Part artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("element", artifact.getElement()); verifyEmptyDerivedRelationships("type", artifact.getType()); } else { Part castOld = (Part) oldArtifact; verifyUnchangedDerivedRelationships("element", artifact.getElement(), castOld.getElement()); verifyUnchangedDerivedRelationships("type", artifact.getType(), castOld.getType()); } } @Override public void visit(PortType artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("operation", artifact.getOperation()); } else { PortType castOld = (PortType) oldArtifact; verifyUnchangedDerivedRelationships("operation", artifact.getOperation(), castOld.getOperation()); } } @Override public void visit(Operation artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("input", artifact.getInput()); verifyEmptyDerivedRelationships("output", artifact.getOutput()); verifyEmptyDerivedRelationships("fault", artifact.getFault()); } else { Operation castOld = (Operation) oldArtifact; verifyUnchangedDerivedRelationships("input", artifact.getInput(), castOld.getInput()); verifyUnchangedDerivedRelationships("output", artifact.getOutput(), castOld.getOutput()); verifyUnchangedDerivedRelationships("fault", artifact.getFault(), castOld.getFault()); } } @Override public void visit(OperationInput artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("message", artifact.getMessage()); } else { OperationInput castOld = (OperationInput) oldArtifact; verifyUnchangedDerivedRelationships("message", artifact.getMessage(), castOld.getMessage()); } } @Override public void visit(OperationOutput artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("message", artifact.getMessage()); } else { OperationOutput castOld = (OperationOutput) oldArtifact; verifyUnchangedDerivedRelationships("message", artifact.getMessage(), castOld.getMessage()); } } @Override public void visit(Fault artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("message", artifact.getMessage()); } else { Fault castOld = (Fault) oldArtifact; verifyUnchangedDerivedRelationships("message", artifact.getMessage(), castOld.getMessage()); } } @Override public void visit(Binding artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("bindingOperation", artifact.getBindingOperation()); verifyEmptyDerivedRelationships("portType", artifact.getPortType()); } else { Binding castOld = (Binding) oldArtifact; verifyUnchangedDerivedRelationships("bindingOperation", artifact.getBindingOperation(), castOld.getBindingOperation()); verifyUnchangedDerivedRelationships("portType", artifact.getPortType(), castOld.getPortType()); } } @Override public void visit(BindingOperation artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("input", artifact.getInput()); verifyEmptyDerivedRelationships("output", artifact.getOutput()); verifyEmptyDerivedRelationships("fault", artifact.getFault()); verifyEmptyDerivedRelationships("operation", artifact.getOperation()); } else { BindingOperation castOld = (BindingOperation) oldArtifact; verifyUnchangedDerivedRelationships("input", artifact.getInput(), castOld.getInput()); verifyUnchangedDerivedRelationships("output", artifact.getOutput(), castOld.getOutput()); verifyUnchangedDerivedRelationships("fault", artifact.getFault(), castOld.getFault()); verifyUnchangedDerivedRelationships("operation", artifact.getOperation(), castOld.getOperation()); } } @Override public void visit(WsdlService artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("port", artifact.getPort()); } else { WsdlService castOld = (WsdlService) oldArtifact; verifyUnchangedDerivedRelationships("port", artifact.getPort(), castOld.getPort()); } } @Override public void visit(Port artifact) { super.visit(artifact); if (oldArtifact == null) { verifyEmptyDerivedRelationships("binding", artifact.getBinding()); } else { Port castOld = (Port) oldArtifact; verifyUnchangedDerivedRelationships("binding", artifact.getBinding(), castOld.getBinding()); } } private void verifyModel(BaseArtifactType artifact) { if (! artifactType.getArtifactType().getApiType().equals(artifact.getArtifactType())) { error = new ArtificerWrongModelException(artifactType.getArtifactType().getApiType().value(), artifact.getArtifactType().value()); } } /** * The S-RAMP spec states that a custom property or generic relationship name cannot duplicate *any* built-in * property/relationship name from *any* S-RAMP type. To conform to that requirement, we'll automate the process * by building a list of all field names in the API. This will define our "reserved keyword" list, even if it is * somewhat more restrictive than the spec requires. * * The spec also requires that, within an artifact, a custom property name cannot duplicate a generic relationship * name (and vice versa). * * @param artifact */ private void verifyNames(BaseArtifactType artifact) { // First, build a list of all the names within this artifact. List<String> propertyNames = new ArrayList<String>(); List<String> relationshipNames = new ArrayList<String>(); for (Property property : artifact.getProperty()) { propertyNames.add(property.getPropertyName()); } for (Relationship relationship : artifact.getRelationship()) { relationshipNames.add(relationship.getRelationshipType()); } // Then, compare against both reserved and local names. for (String propertyName : propertyNames) { if (isReserved(propertyName)) { error = ArtificerConflictException.reservedName(propertyName); } if (relationshipNames.contains(propertyName)) { error = ArtificerConflictException.duplicateName(propertyName); } if (Collections.frequency(propertyNames, propertyName) > 1) { error = ArtificerConflictException.duplicateName(propertyName); } } for (String relationshipName : relationshipNames) { // "relatedDocument" is a unique case. Due to shortcomings in the S-RAMP spec, it's an actual field // on DerivedArtifactType. But, we also have to use it as a general relationship, since there is no // DerivedExtendedArtifactType (ie, if an extended artifact type is derived, it also needs that field, // but doesn't). // TODO: Fix that! if (!relationshipName.equals("relatedDocument")) { if (isReserved(relationshipName)) { error = ArtificerConflictException.reservedName(relationshipName); } if (propertyNames.contains(relationshipName)) { error = ArtificerConflictException.duplicateName(relationshipName); } } } } private boolean isReserved(String s) { return reservedNames.contains(s.toLowerCase()); } private void verifyEmptyDerivedRelationships(String relationshipType, Collection<?> relationships) { if (!relationships.isEmpty()) { error = ArtificerConflictException.derivedRelationshipCreation(relationshipType); } } private void verifyEmptyDerivedRelationships(String relationshipType, Object relationship) { if (relationship != null) { error = ArtificerConflictException.derivedRelationshipCreation(relationshipType); } } private void verifyUnchangedDerivedRelationships(String relationshipType, Collection<?> relationships, Collection<?> oldRelationships) { // TODO: We'll eventually be introducing artifact deep comparisons. But until then, just keep this simple... if (relationships.size() != oldRelationships.size()) { error = ArtificerConflictException.derivedRelationshipCreation(relationshipType); } } private void verifyUnchangedDerivedRelationships(String relationshipType, Object relationship, Object oldRelationship) { // TODO: We'll eventually be introducing artifact deep comparisons. But until then, just keep this simple... if ((oldRelationship != null && relationship == null) || (oldRelationship == null && relationship != null)) { error = ArtificerConflictException.derivedRelationshipCreation(relationshipType); } } }