| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF 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.apache.tuscany.sca.assembly.xml; |
| |
| import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; |
| import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.CALLBACK; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.CALLBACK_QNAME; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.COMPONENT_TYPE; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.COMPONENT_TYPE_QNAME; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.ELEMENT; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.IMPLEMENTATION; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.MANY; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.MUST_SUPPLY; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.NAME; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.OPERATION_QNAME; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.PROPERTY; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.PROPERTY_QNAME; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.REFERENCE; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.REFERENCE_QNAME; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.SERVICE; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.SERVICE_QNAME; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.TYPE; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.EXTENSION; |
| import static org.apache.tuscany.sca.assembly.xml.Constants.EXTENSION_QNAME; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.stream.XMLStreamConstants; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamReader; |
| import javax.xml.stream.XMLStreamWriter; |
| |
| import org.apache.tuscany.sca.assembly.Binding; |
| import org.apache.tuscany.sca.assembly.Callback; |
| import org.apache.tuscany.sca.assembly.ComponentType; |
| import org.apache.tuscany.sca.assembly.Contract; |
| import org.apache.tuscany.sca.assembly.Extensible; |
| import org.apache.tuscany.sca.assembly.Property; |
| import org.apache.tuscany.sca.assembly.Reference; |
| import org.apache.tuscany.sca.assembly.Service; |
| import org.apache.tuscany.sca.common.xml.stax.StAXHelper; |
| import org.apache.tuscany.sca.contribution.processor.ContributionReadException; |
| import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; |
| import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; |
| import org.apache.tuscany.sca.contribution.processor.ProcessorContext; |
| import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; |
| import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor; |
| import org.apache.tuscany.sca.contribution.resolver.ModelResolver; |
| import org.apache.tuscany.sca.core.ExtensionPointRegistry; |
| import org.apache.tuscany.sca.core.FactoryExtensionPoint; |
| import org.apache.tuscany.sca.interfacedef.InterfaceContract; |
| import org.apache.tuscany.sca.interfacedef.Operation; |
| import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; |
| import org.apache.tuscany.sca.policy.PolicySubject; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * A componentType processor. |
| * |
| * @version $Rev$ $Date$ |
| */ |
| public class ComponentTypeProcessor extends BaseAssemblyProcessor implements StAXArtifactProcessor<ComponentType> { |
| |
| private StAXHelper staxHelper; |
| |
| /** |
| * Constructs a new componentType processor. |
| * |
| * @param modelFactories |
| * @param extensionProcessor |
| * @param extensionAttributeProcessor |
| * @param monitor |
| */ |
| public ComponentTypeProcessor(ExtensionPointRegistry extensionPoints, |
| //public ComponentTypeProcessor(FactoryExtensionPoint modelFactories, |
| StAXArtifactProcessor extensionProcessor, |
| StAXAttributeProcessor extensionAttributeProcessor) { |
| super(modelFactories(extensionPoints), extensionProcessor); |
| |
| // |
| staxHelper = StAXHelper.getInstance(extensionPoints); |
| } |
| |
| public ComponentType read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException { |
| ComponentType componentType = null; |
| Service service = null; |
| Reference reference = null; |
| Contract contract = null; |
| Property property = null; |
| Callback callback = null; |
| QName name = null; |
| |
| try { |
| // Read the componentType document |
| while (reader.hasNext()) { |
| int event = reader.getEventType(); |
| switch (event) { |
| case START_ELEMENT: |
| name = reader.getName(); |
| |
| if (Constants.COMPONENT_TYPE_QNAME.equals(name)) { |
| |
| // Read a <componentType> |
| componentType = assemblyFactory.createComponentType(); |
| |
| } else if (Constants.SERVICE_QNAME.equals(name)) { |
| |
| // Read a <service> |
| service = assemblyFactory.createService(); |
| contract = service; |
| service.setName(getString(reader, Constants.NAME)); |
| componentType.getServices().add(service); |
| policyProcessor.readPolicies(service, reader); |
| |
| } else if (Constants.REFERENCE_QNAME.equals(name)) { |
| |
| // Read a <reference> |
| reference = assemblyFactory.createReference(); |
| contract = reference; |
| reference.setName(getString(reader, Constants.NAME)); |
| reference.setWiredByImpl(getBoolean(reader, Constants.WIRED_BY_IMPL)); |
| readMultiplicity(reference, reader); |
| readTargets(reference, reader); |
| componentType.getReferences().add(reference); |
| policyProcessor.readPolicies(reference, reader); |
| |
| } else if (Constants.PROPERTY_QNAME.equals(name)) { |
| |
| // Read a <property> |
| property = assemblyFactory.createProperty(); |
| readAbstractProperty(property, reader, context); |
| policyProcessor.readPolicies(property, reader); |
| |
| // Read the property value |
| Document value = readPropertyValue(property.getXSDElement(), property.getXSDType(), property.isMany(), reader, context); |
| property.setValue(value); |
| |
| componentType.getProperties().add(property); |
| |
| } else if (Constants.IMPLEMENTATION_QNAME.equals(name)) { |
| |
| // Read an <implementation> element |
| policyProcessor.readPolicies(componentType, reader); |
| |
| } else if (Constants.CALLBACK_QNAME.equals(name)) { |
| |
| // Read a <callback> |
| callback = assemblyFactory.createCallback(); |
| contract.setCallback(callback); |
| policyProcessor.readPolicies(callback, reader); |
| |
| } else if (OPERATION_QNAME.equals(name)) { |
| |
| // Read an <operation> |
| Operation operation = new OperationImpl(); |
| operation.setName(getString(reader, NAME)); |
| operation.setUnresolved(true); |
| if (callback != null) { |
| policyProcessor.readPolicies(callback, operation, reader); |
| } else { |
| policyProcessor.readPolicies(contract, operation, reader); |
| } |
| } else if(EXTENSION_QNAME.equals(name)) { |
| // Handle <extension> |
| //ignore element as this is a wrapper for extensibility |
| break; |
| } else { |
| |
| |
| // Read an extension element |
| Object extension = extensionProcessor.read(reader, context); |
| if (extension != null) { |
| if (extension instanceof InterfaceContract) { |
| |
| // <service><interface> and <reference><interface> |
| contract.setInterfaceContract((InterfaceContract)extension); |
| |
| } else if (extension instanceof Binding) { |
| |
| // <service><binding> and <reference><binding> |
| if (callback != null) { |
| callback.getBindings().add((Binding)extension); |
| } else { |
| contract.getBindings().add((Binding)extension); |
| } |
| } else { |
| |
| // Add the extension element to the current element |
| if (callback != null) { |
| callback.getExtensions().add(extension); |
| } else if (contract != null) { |
| contract.getExtensions().add(extension); |
| } else if (property != null) { |
| property.getExtensions().add(extension); |
| } else { |
| if (componentType instanceof Extensible) { |
| ((Extensible)componentType).getExtensions().add(extension); |
| } |
| } |
| } |
| } |
| } |
| break; |
| |
| case END_ELEMENT: |
| name = reader.getName(); |
| |
| // Clear current state when reading reaching end element |
| if (SERVICE_QNAME.equals(name)) { |
| service = null; |
| contract = null; |
| } else if (REFERENCE_QNAME.equals(name)) { |
| reference = null; |
| contract = null; |
| } else if (PROPERTY_QNAME.equals(name)) { |
| property = null; |
| } else if (CALLBACK_QNAME.equals(name)) { |
| callback = null; |
| } |
| break; |
| } |
| |
| // Read the next element |
| if (reader.hasNext()) { |
| reader.next(); |
| } |
| } |
| } |
| catch (XMLStreamException e) { |
| ContributionReadException ex = new ContributionReadException(e); |
| error(context.getMonitor(), "XMLStreamException", reader, ex); |
| } |
| |
| return componentType; |
| } |
| |
| public void write(ComponentType componentType, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException { |
| |
| // Write <componentType> element |
| writeStartDocument(writer, COMPONENT_TYPE); |
| |
| // Write <service> elements |
| for (Service service : componentType.getServices()) { |
| writeStart(writer, SERVICE, new XAttr(NAME, service.getName()), |
| policyProcessor.writePolicies(service)); |
| |
| if (service.getInterfaceContract() != null) { |
| extensionProcessor.write(service.getInterfaceContract(), writer, context); |
| } |
| |
| for (Binding binding: service.getBindings()) { |
| extensionProcessor.write(binding, writer, context); |
| } |
| |
| if (service.getCallback() != null) { |
| Callback callback = service.getCallback(); |
| writeStart(writer, CALLBACK, policyProcessor.writePolicies(callback)); |
| |
| for (Binding binding: callback.getBindings()) { |
| extensionProcessor.write(binding, writer, context); |
| } |
| for (Object extension: callback.getExtensions()) { |
| extensionProcessor.write(extension, writer, context); |
| } |
| |
| writeEnd(writer); |
| } |
| |
| this.writeExtendedElements(writer, service, extensionProcessor, context); |
| |
| writeEnd(writer); |
| } |
| |
| // Write <reference> elements |
| for (Reference reference : componentType.getReferences()) { |
| |
| writeStart(writer, REFERENCE, |
| new XAttr(NAME, reference.getName()), |
| writeMultiplicity(reference), |
| writeTargets(reference), |
| policyProcessor.writePolicies(reference)); |
| |
| extensionProcessor.write(reference.getInterfaceContract(), writer, context); |
| |
| for (Binding binding: reference.getBindings()) { |
| extensionProcessor.write(binding, writer, context); |
| } |
| |
| if (reference.getCallback() != null) { |
| Callback callback = reference.getCallback(); |
| writeStart(writer, CALLBACK, |
| policyProcessor.writePolicies(callback)); |
| |
| for (Binding binding: callback.getBindings()) { |
| extensionProcessor.write(binding, writer, context); |
| } |
| for (Object extension: callback.getExtensions()) { |
| extensionProcessor.write(extension, writer, context); |
| } |
| |
| writeEnd(writer); |
| } |
| |
| this.writeExtendedElements(writer, reference, extensionProcessor, context); |
| |
| writeEnd(writer); |
| } |
| |
| // Write <property> elements |
| for (Property property : componentType.getProperties()) { |
| writeStart(writer, |
| PROPERTY, |
| new XAttr(NAME, property.getName()), |
| new XAttr(MUST_SUPPLY, property.isMustSupply()), |
| new XAttr(MANY, property.isMany()), |
| new XAttr(TYPE, property.getXSDType()), |
| new XAttr(ELEMENT, property.getXSDElement()), |
| policyProcessor.writePolicies(property)); |
| |
| // Write property value |
| writePropertyValue(property.getValue(), property.getXSDElement(), property.getXSDType(), writer); |
| |
| // Write extensions |
| for (Object extension : property.getExtensions()) { |
| extensionProcessor.write(extension, writer, context); |
| } |
| |
| writeEnd(writer); |
| } |
| |
| // Write extension elements |
| if (componentType instanceof Extensible) { |
| for (Object extension: ((Extensible)componentType).getExtensions()) { |
| extensionProcessor.write(extension, writer, context); |
| } |
| } |
| |
| // Write <implementation> elements if the componentType has |
| // any intents or policySets |
| boolean writeImplementation = false; |
| if (componentType instanceof PolicySubject) { |
| if (!((PolicySubject)componentType).getRequiredIntents().isEmpty()) { |
| writeImplementation = true; |
| } |
| } |
| if (componentType instanceof PolicySubject) { |
| if (!((PolicySubject)componentType).getPolicySets().isEmpty()) { |
| writeImplementation = true; |
| } |
| } |
| if (writeImplementation) { |
| writeStart(writer, IMPLEMENTATION, |
| policyProcessor.writePolicies(componentType)); |
| } |
| |
| writeEndDocument(writer); |
| } |
| |
| /** |
| * Write the value of a property - override to use correct method of creating an XMLStreamReader |
| * @param document |
| * @param element |
| * @param type |
| * @param writer |
| * @throws XMLStreamException |
| */ |
| protected void writePropertyValue(Object propertyValue, QName element, QName type, XMLStreamWriter writer) |
| throws XMLStreamException { |
| |
| if (propertyValue instanceof Document) { |
| Document document = (Document)propertyValue; |
| NodeList nodeList = document.getDocumentElement().getChildNodes(); |
| |
| for (int item = 0; item < nodeList.getLength(); ++item) { |
| Node node = nodeList.item(item); |
| int nodeType = node.getNodeType(); |
| if (nodeType == Node.ELEMENT_NODE) { |
| // Correct way to create a reader for a node object... |
| XMLStreamReader reader = staxHelper.createXMLStreamReader(node); |
| |
| while (reader.hasNext()) { |
| switch (reader.next()) { |
| case XMLStreamConstants.START_ELEMENT: |
| QName name = reader.getName(); |
| writer.writeStartElement(name.getPrefix(), name.getLocalPart(), name.getNamespaceURI()); |
| |
| int namespaces = reader.getNamespaceCount(); |
| for (int i = 0; i < namespaces; i++) { |
| String prefix = reader.getNamespacePrefix(i); |
| String ns = reader.getNamespaceURI(i); |
| writer.writeNamespace(prefix, ns); |
| } |
| |
| if (!"".equals(name.getNamespaceURI())) { |
| writer.writeNamespace(name.getPrefix(), name.getNamespaceURI()); |
| } |
| |
| // add the attributes for this element |
| namespaces = reader.getAttributeCount(); |
| for (int i = 0; i < namespaces; i++) { |
| String ns = reader.getAttributeNamespace(i); |
| String prefix = reader.getAttributePrefix(i); |
| String qname = reader.getAttributeLocalName(i); |
| String value = reader.getAttributeValue(i); |
| |
| writer.writeAttribute(prefix, ns, qname, value); |
| } |
| |
| break; |
| case XMLStreamConstants.CDATA: |
| writer.writeCData(reader.getText()); |
| break; |
| case XMLStreamConstants.CHARACTERS: |
| writer.writeCharacters(reader.getText()); |
| break; |
| case XMLStreamConstants.END_ELEMENT: |
| writer.writeEndElement(); |
| break; |
| } |
| } |
| } else { |
| writer.writeCharacters(node.getTextContent()); |
| } |
| } |
| } |
| } // end method writePropertyValue |
| |
| public void resolve(ComponentType componentType, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { |
| |
| // Resolve component type services and references |
| resolveContracts(componentType.getServices(), resolver, context); |
| resolveContracts(componentType.getReferences(), resolver, context); |
| } |
| |
| public QName getArtifactType() { |
| return COMPONENT_TYPE_QNAME; |
| } |
| |
| public Class<ComponentType> getModelType() { |
| return ComponentType.class; |
| } |
| |
| /** |
| * Returns the model factory extension point to use. |
| * |
| * @param extensionPoints |
| * @return |
| */ |
| private static FactoryExtensionPoint modelFactories(ExtensionPointRegistry extensionPoints) { |
| return extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); |
| } |
| } |