001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.webservices;
018    
019    import java.util.ArrayList;
020    import java.util.Map;
021    import javax.wsdl.*;
022    import javax.wsdl.extensions.soap.SOAPBinding;
023    import javax.wsdl.extensions.soap.SOAPBody;
024    import javax.xml.namespace.QName;
025    
026    import org.apache.geronimo.validator.ValidationContext;
027    import org.apache.geronimo.validator.ValidationFailure;
028    
029    public class LightWeightMappingValidator extends WSDLVisitor {
030    
031        private ArrayList operationNames;
032        private ValidationContext context;
033    
034        private static final QName XSD_STRING = new QName("http://www.w3.org/2001/XMLSchema", "string");
035    
036        public LightWeightMappingValidator(Definition definition) {
037            super(definition);
038        }
039    
040        public ValidationContext validate() {
041            if (context == null) {
042                context = new ValidationContext(definition.getQName().toString());
043                walkTree();
044            }
045            return context;
046        }
047    
048        public boolean isValid() {
049            ValidationContext context = validate();
050            return !context.hasFailures() && !context.hasErrors();
051        }
052    
053        protected void begin() {
054            operationNames = new ArrayList();
055        }
056    
057        protected void visit(Definition definition) {
058            if (definition.getServices().values().size() != 1) {
059                context.addFailure(new ValidationFailure("A lightweight RPC/Encoded service must contain only one Service"));
060            }
061        }
062    
063        protected void visit(Output output) {
064            Map outputParts = output.getMessage().getParts();
065            if (outputParts.size() != 0 && outputParts.size() != 1) {
066                context.addFailure(new ValidationFailure("The output message must contain zero or one parts: " + output.getName()));
067            }
068    
069        }
070    
071        protected void visit(Operation operation) {
072            if (!operationNames.add(operation.getName())) {
073                context.addFailure(new ValidationFailure("No two operations can have the same name: " + operation.getName()));
074            }
075        }
076    
077        protected void visit(Fault fault) {
078            Part message = fault.getMessage().getPart("message");
079            if (message == null) {
080                context.addFailure(new ValidationFailure("The fault message must contain one part named 'message' : " + fault.getName()));
081            } else if (!XSD_STRING.equals(message.getTypeName())) {
082                context.addFailure(new ValidationFailure("The fault message must contain one part of type 'xsd:string' : " + fault.getName()));
083            }
084        }
085    
086    
087        protected void visit(BindingInput bindingInput) {
088            SOAPBody body = getSOAPBody(bindingInput.getExtensibilityElements());
089            String encoding = body.getUse();
090            if (encoding == null || !encoding.equals("encoded")) {
091                context.addFailure(new ValidationFailure("The use attribute of the binding input operation must be 'encoded': " + bindingInput.getName()));
092            }
093        }
094    
095        protected void visit(BindingOutput bindingOutput) {
096            SOAPBody body = getSOAPBody(bindingOutput.getExtensibilityElements());
097            String encoding = body.getUse();
098            if (encoding == null || !encoding.equals("encoded")) {
099                context.addFailure(new ValidationFailure("The use attribute of the binding output operation must be 'encoded': " + bindingOutput.getName()));
100            }
101        }
102    
103        protected void visit(BindingFault bindingFault) {
104            SOAPBody body = getSOAPBody(bindingFault.getExtensibilityElements());
105            String encoding = body.getUse();
106            if (encoding == null || !encoding.equals("encoded")) {
107                context.addFailure(new ValidationFailure("The use attribute of the binding fault operation must be 'encoded': " + bindingFault.getName()));
108            }
109        }
110    
111        protected void visit(Binding binding) {
112            SOAPBinding soapBinding = getSOAPBinding(binding);
113            if (soapBinding == null || soapBinding.getStyle() == null || !soapBinding.getStyle().equals("rpc")) {
114                context.addFailure(new ValidationFailure("The messaging style of the binding must be rpc: " + binding.getQName()));
115            }
116        }
117    
118        protected void visit(Service service) {
119            if (service.getPorts().values().size() != 1) {
120                context.addFailure(new ValidationFailure("A lightweight RPC/Encoded service must contain only one Port"));
121            }
122        }
123    }