diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2008-09-15 00:26:00 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2008-09-15 00:26:00 +0000 |
commit | d5f1d093fe6fa491cdec392dca7137639e98d149 (patch) | |
tree | b98c79d8231a2617ee1dce43b1782d30d93686bc /branches/sca-android/modules/databinding | |
parent | f4e3e383071b6947d56794d9af5e9e6438aa3235 (diff) |
Pulled a recent revision of trunk into the sca-android branch, to apply the android patches from JIRA TUSCANY-2440 to it.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@695318 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
362 files changed, 38212 insertions, 0 deletions
diff --git a/branches/sca-android/modules/databinding-axiom/LICENSE b/branches/sca-android/modules/databinding-axiom/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/branches/sca-android/modules/databinding-axiom/NOTICE b/branches/sca-android/modules/databinding-axiom/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-axiom/pom.xml b/branches/sca-android/modules/databinding-axiom/pom.xml new file mode 100644 index 0000000000..f602ad3519 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/pom.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-axiom</artifactId> + <name>Apache Tuscany SCA Data Binding for Axiom</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>javax.xml.stream</groupId> + <artifactId>stax-api</artifactId> + <version>1.0-2</version> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-api</artifactId> + <version>1.2.5</version> + <exclusions> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + <exclusion> + <groupId>xml-apis</groupId> + <artifactId>xml-apis</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-impl</artifactId> + <version>1.2.5</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>wstx-asl</artifactId> + <version>3.2.1</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.axiom</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.axiom*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/AxiomDataBinding.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/AxiomDataBinding.java new file mode 100644 index 0000000000..e59038bfa1 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/AxiomDataBinding.java @@ -0,0 +1,63 @@ +/*
+ * 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.databinding.axiom;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.tuscany.sca.databinding.WrapperHandler;
+import org.apache.tuscany.sca.databinding.impl.BaseDataBinding;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+
+/**
+ * DataBinding for AXIOM
+ *
+ * @version $Rev$ $Date$
+ */
+public class AxiomDataBinding extends BaseDataBinding {
+
+ public static final String NAME = OMElement.class.getName();
+ public static final String[] ALIASES = new String[] {"axiom"};
+
+ public AxiomDataBinding() {
+ super(NAME, ALIASES, OMElement.class);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.databinding.impl.BaseDataBinding#getWrapperHandler()
+ */
+ @Override
+ public WrapperHandler getWrapperHandler() {
+ return new OMElementWrapperHandler();
+ }
+
+ @Override
+ public Object copy(Object source, DataType dataType, Operation operation) {
+ if ( OMElement.class.isAssignableFrom(source.getClass()) ) {
+ try {
+ OMElement sourceElement = (OMElement)source;
+ return sourceElement.cloneOMElement();
+ } catch ( Exception e ) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ return super.copy(source, dataType, operation);
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/AxiomHelper.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/AxiomHelper.java new file mode 100644 index 0000000000..cd820ab4b4 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/AxiomHelper.java @@ -0,0 +1,142 @@ +/* + * 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.databinding.axiom; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMDataSource; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.axiom.om.OMXMLParserWrapper; +import org.apache.axiom.om.impl.builder.StAXBuilder; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Helper for AXIOM + * + * @version $Rev$ $Date$ + */ +public class AxiomHelper { + private static final String DEFAULT_PREFIX = "_ns_"; + + private AxiomHelper() { + } + + /** + * See http://issues.apache.org/jira/browse/WSCOMMONS-240 + * @param om + */ + public static void completeAndClose(OMElement om) { + // Get the builder associated with the om element + OMXMLParserWrapper builder = om.getBuilder(); + if (builder != null) { + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).releaseParserOnClose(true); + } + OMElement document = builder.getDocumentElement(); + if (document != null) { + document.build(); + } + } + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).close(); + } + } + + /** + * This method will close the builder immediately. Any subsequent Axiom objects won't + * be built or accessible. + */ + public static void closeImmediately(OMElement om) { + // Get the builder associated with the om element + OMXMLParserWrapper builder = om.getBuilder(); + if (builder != null) { + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).releaseParserOnClose(true); + ((StAXBuilder)builder).close(); + } + // builder.close(); + } + } + + /** + * @param context + * @param element + */ + public static void adjustElementName(TransformationContext context, OMElement element) { + if (context != null) { + DataType dataType = context.getTargetDataType(); + Object logical = dataType == null ? null : dataType.getLogical(); + if (!(logical instanceof XMLType)) { + return; + } + XMLType xmlType = (XMLType)logical; + if (xmlType.isElement() && !xmlType.getElementName().equals(element.getQName())) { + // FIXME:: Throw exception or switch to the new Element? + OMFactory factory = OMAbstractFactory.getOMFactory(); + QName name = xmlType.getElementName(); + OMNamespace namespace = factory.createOMNamespace(name.getNamespaceURI(), name.getPrefix()); + element.setNamespace(namespace); + element.setLocalName(name.getLocalPart()); + } + } + } + + public static OMElement createOMElement(OMFactory factory, QName element) { + String localName = element.getLocalPart(); + OMNamespace ns = createOMNamespace(factory, element); + + return factory.createOMElement(localName, ns); + + } + + public static OMElement createOMElement(OMFactory factory, QName element, OMDataSource dataSource) { + String localName = element.getLocalPart(); + OMNamespace ns = createOMNamespace(factory, element); + + return factory.createOMElement(dataSource, localName, ns); + + } + + /** + * @param factory + * @param name + * @return + */ + public static OMNamespace createOMNamespace(OMFactory factory, QName name) { + String namespaceURI = name.getNamespaceURI(); + String prefix = name.getPrefix(); + + OMNamespace ns = null; + + // Qualified Element: we need an OMNamespace + if (prefix.length() == 0) { + // The prefix does not appear to be specified, let's create one + prefix = DEFAULT_PREFIX; + } + ns = factory.createOMNamespace(namespaceURI, prefix); + + return ns; + } +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Exception2OMElement.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Exception2OMElement.java new file mode 100644 index 0000000000..429a6dbe5d --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Exception2OMElement.java @@ -0,0 +1,95 @@ +/*
+ * 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.databinding.axiom;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMAttribute;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMNamespace;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.javabeans.Java2XMLMapperException;
+import org.apache.tuscany.sca.databinding.javabeans.JavaBean2XMLTransformer;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class Exception2OMElement extends JavaBean2XMLTransformer<OMElement> {
+
+ public static final String GETCAUSE = "getCause";
+ public static final String GETLOCALIZEDMESSAGE = "getLocalizedMessage";
+ public static final String GETSTACKTRACE = "getStackTrace";
+ public static final String GETCLASS = "getClass";
+
+ private OMFactory factory;
+
+ public Exception2OMElement() {
+ super();
+ factory = OMAbstractFactory.getOMFactory();
+ }
+
+ @Override
+ public OMElement transform(Object source, TransformationContext context) {
+ OMElement element = super.transform(source, context);
+ AxiomHelper.adjustElementName(context, element);
+ return element;
+ }
+
+ @Override
+ protected boolean isMappedGetter(String methodName) {
+ if (GETCAUSE.equals(methodName)
+ || GETLOCALIZEDMESSAGE.equals(methodName)
+ || GETSTACKTRACE.equals(methodName)
+ || GETCLASS.equals(methodName)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void appendChild(OMElement parentElement, OMElement childElement) throws Java2XMLMapperException {
+ parentElement.addChild(childElement);
+ }
+
+ @Override
+ public OMElement createElement(QName qName) throws Java2XMLMapperException {
+ return factory.createOMElement(qName);
+ }
+
+ @Override
+ public void appendText(OMElement parentElement, String textData) throws Java2XMLMapperException {
+ if (textData == null) {
+ OMNamespace xsi = factory.createOMNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi");
+ OMAttribute nil = factory.createOMAttribute("nil", xsi, "true");
+ parentElement.addAttribute(nil);
+ } else {
+ factory.createOMText(parentElement, textData);
+ }
+ }
+
+ @Override
+ public Class getTargetType() {
+ return OMElement.class;
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Externalizable2OMElement.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Externalizable2OMElement.java new file mode 100644 index 0000000000..e23d89327c --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Externalizable2OMElement.java @@ -0,0 +1,77 @@ +/*
+ * 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.databinding.axiom;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.ObjectOutputStream;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMNamespace;
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter.Base64Binary;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class Externalizable2OMElement extends BaseTransformer<Externalizable, OMElement> implements
+ PullTransformer<Externalizable, OMElement> {
+
+ @Override
+ protected Class<Externalizable> getSourceType() {
+ return Externalizable.class;
+ }
+
+ @Override
+ protected Class<OMElement> getTargetType() {
+ return OMElement.class;
+ }
+
+ public OMElement transform(Externalizable source, TransformationContext context) {
+ OMElement element = null;
+
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(bos);
+ out.writeObject(source);
+ out.close();
+ OMFactory factory = OMAbstractFactory.getOMFactory();
+ OMNamespace ns = AxiomHelper.createOMNamespace(factory, new QName("http://callable"));
+ element = factory.createOMElement("reference",ns);
+ element.setText(Base64Binary.encode(bos.toByteArray()));
+ return element;
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ public int getWeight() {
+ return 10;
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Exception.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Exception.java new file mode 100644 index 0000000000..3dc73c89cb --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Exception.java @@ -0,0 +1,79 @@ +/*
+ * 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.databinding.axiom;
+
+import java.util.Iterator;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMNode;
+import org.apache.axiom.om.OMText;
+import org.apache.tuscany.sca.databinding.javabeans.XML2JavaBeanTransformer;
+import org.apache.tuscany.sca.databinding.javabeans.XML2JavaMapperException;
+
+/**
+ * Transformer to convert data from an OMElement to a Java Exception
+ *
+ * @version $Rev$ $Date$
+ */
+public class OMElement2Exception extends XML2JavaBeanTransformer<OMElement> {
+
+ @Override
+ public OMElement getRootElement(OMElement element) throws XML2JavaMapperException {
+ return element;
+ }
+
+ @Override
+ public Iterator<OMElement> getChildElements(OMElement parent) throws XML2JavaMapperException {
+ return parent.getChildElements();
+ }
+
+ @Override
+ public String getElementName(OMElement element) throws XML2JavaMapperException {
+ return element.getLocalName();
+ }
+
+ @Override
+ public String getText(OMElement element) throws XML2JavaMapperException {
+ return element.getText();
+ }
+
+ @Override
+ public boolean isTextElement(OMElement element) throws XML2JavaMapperException {
+ return false;
+ }
+
+ @Override
+ public boolean isTextOnly(OMElement element) throws XML2JavaMapperException {
+ OMNode firstChild = element.getFirstOMChild();
+ return firstChild instanceof OMText && firstChild.getNextOMSibling() == null;
+ }
+
+ @Override
+ public OMElement getFirstChildWithName(OMElement element, QName name) throws XML2JavaMapperException {
+ return element.getFirstChildWithName(name);
+ }
+
+ @Override
+ public Class getSourceType() {
+ return OMElement.class;
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Externalizable.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Externalizable.java new file mode 100644 index 0000000000..ef7359fbcd --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Externalizable.java @@ -0,0 +1,69 @@ +/*
+ * 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.databinding.axiom;
+
+import java.io.ByteArrayInputStream;
+import java.io.Externalizable;
+import java.io.ObjectInputStream;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter.Base64Binary;
+
+/**
+ * Transformer to convert data from an OMElement to XML String
+ *
+ * @version $Rev$ $Date$
+ */
+public class OMElement2Externalizable extends BaseTransformer<OMElement, Externalizable> implements PullTransformer<OMElement, Externalizable> {
+ // private XmlOptions options;
+
+ public Externalizable transform(OMElement source, TransformationContext context) {
+ try {
+ String value = source.getText();
+ ByteArrayInputStream bis = new ByteArrayInputStream(Base64Binary.decode(value));
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ Object obj = ois.readObject();
+ ois.close();
+ Externalizable aReference = (Externalizable) obj;
+ return aReference;
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class<OMElement> getSourceType() {
+ return OMElement.class;
+ }
+
+ @Override
+ protected Class<Externalizable> getTargetType() {
+ return Externalizable.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 10;
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Object.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Object.java new file mode 100644 index 0000000000..ea40e61746 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2Object.java @@ -0,0 +1,50 @@ +/* + * 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.databinding.axiom; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.impl.SimpleType2JavaTransformer; + +/** + * Transformer to convert data from a simple java Object to OMElement. + * + * @version $Rev$ $Date$ + */ +public class OMElement2Object extends SimpleType2JavaTransformer<OMElement> { + + /** + * @see org.apache.tuscany.sca.databinding.impl.SimpleType2JavaTransformer#close(java.lang.Object) + */ + @Override + protected void close(OMElement source) { + if (source != null) { + AxiomHelper.completeAndClose(source); + } + } + + @Override + protected String getText(OMElement source) { + return source.getText(); + } + + @Override + public Class getSourceType() { + return OMElement.class; + } +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2String.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2String.java new file mode 100644 index 0000000000..b2c004324c --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2String.java @@ -0,0 +1,64 @@ +/* + * 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.databinding.axiom; + +import java.io.StringWriter; + +import javax.xml.stream.XMLStreamException; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * Transformer to convert data from an OMElement to XML String + * + * @version $Rev$ $Date$ + */ +public class OMElement2String extends BaseTransformer<OMElement, String> implements PullTransformer<OMElement, String> { + // private XmlOptions options; + + public String transform(OMElement source, TransformationContext context) { + try { + StringWriter writer = new StringWriter(); + source.serialize(writer); + return writer.toString(); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<OMElement> getSourceType() { + return OMElement.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2XMLStreamReader.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2XMLStreamReader.java new file mode 100644 index 0000000000..01e7003b20 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElement2XMLStreamReader.java @@ -0,0 +1,66 @@ +/* + * 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.databinding.axiom; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * + * @version $Rev$ $Date$ + */ +public class OMElement2XMLStreamReader extends BaseTransformer<OMElement, XMLStreamReader> implements + PullTransformer<OMElement, XMLStreamReader> { + // private XmlOptions options; + + public static final QName QNAME_NIL = new QName("http://www.w3.org/2001/XMLSchema-instance", "nil"); + + public XMLStreamReader transform(OMElement source, TransformationContext context) { + if (source == null) { + return null; + } else { + if ("true".equals(source.getAttributeValue(QNAME_NIL))) { + return null; + } else { + return source.getXMLStreamReader(); + } + } + } + + @Override + protected Class<OMElement> getSourceType() { + return OMElement.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElementWrapperHandler.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElementWrapperHandler.java new file mode 100644 index 0000000000..9084f09dc0 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/OMElementWrapperHandler.java @@ -0,0 +1,251 @@ +/* + * 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.databinding.axiom; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMAttribute; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * OMElement wrapper handler implementation + * + * @version $Rev$ $Date$ + */ +public class OMElementWrapperHandler implements WrapperHandler<OMElement> { + + private OMFactory factory; + + public OMElementWrapperHandler() { + super(); + this.factory = OMAbstractFactory.getOMFactory(); + } + + public OMElement create(Operation operation, boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + // Class<?> wrapperClass = input ? wrapperInfo.getInputWrapperClass() : wrapperInfo.getOutputWrapperClass(); + OMElement wrapper = AxiomHelper.createOMElement(factory, element.getQName()); + return wrapper; + } + + public void setChildren(OMElement wrapper, Object[] childObjects, Operation operation, boolean input) { + List<ElementInfo> childElements = + input ? operation.getWrapper().getInputChildElements() : operation.getWrapper().getOutputChildElements(); + for (int i = 0; i < childElements.size(); i++) { + setChild(wrapper, i, childElements.get(i), childObjects[i]); + } + + } + + public void setChild(OMElement wrapper, int i, ElementInfo childElement, Object value) { + if (childElement.isMany()) { + Object[] elements = (Object[])value; + if (value != null) { + for (Object e : elements) { + addChild(wrapper, childElement, (OMElement)e); + } + } + } else { + OMElement element = (OMElement)value; + addChild(wrapper, childElement, element); + } + } + + private void addChild(OMElement wrapper, ElementInfo childElement, OMElement element) { + if (element == null) { + OMElement e = wrapper.getOMFactory().createOMElement(childElement.getQName(), wrapper); + attachXSINil(e); + return; + } + QName elementName = childElement.getQName(); + // Make it a bit tolerating of element QName + if (!elementName.equals(element.getQName())) { + OMNamespace namespace = factory.createOMNamespace(elementName.getNamespaceURI(), elementName.getPrefix()); + element.setNamespace(namespace); + element.setLocalName(childElement.getQName().getLocalPart()); + } + wrapper.addChild(element); + } + + public List getChildren(OMElement wrapper, Operation operation, boolean input) { + List<ElementInfo> childElements = input? operation.getWrapper().getInputChildElements(): + operation.getWrapper().getOutputChildElements(); + + List<Object> elements = new ArrayList<Object>(); + int i = 0; + for (ElementInfo e : childElements) { + elements.add(getChild(wrapper, e, i)); + i++; + } + return elements; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getWrapperType(Operation, boolean) + */ + public DataType getWrapperType(Operation operation, boolean input) { + WrapperInfo wrapper = operation.getWrapper(); + ElementInfo element = input ? wrapper.getInputWrapperElement() : wrapper.getOutputWrapperElement(); + DataType<XMLType> wrapperType = + new DataTypeImpl<XMLType>(AxiomDataBinding.NAME, OMElement.class, new XMLType(element)); + return wrapperType; + } + + public boolean isInstance(Object wrapperObj, Operation operation, boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + // List<ElementInfo> childElements = + // input ? wrapperInfo.getInputChildElements() : wrapperInfo.getOutputChildElements(); + OMElement wrapper = (OMElement)wrapperObj; + if (!element.getQName().equals(wrapper.getQName())) { + return false; + } + return true; + /* + Set<QName> names = new HashSet<QName>(); + for (ElementInfo e : childElements) { + names.add(e.getQName()); + } + for (Iterator i = wrapper.getChildElements(); i.hasNext();) { + OMElement child = (OMElement)i.next(); + if (!names.contains(child.getQName())) { + return false; + } + } + return true; + */ + } + + private static final QName XSI_TYPE_QNAME = new QName("http://www.w3.org/2001/XMLSchema-instance", "type", "xsi"); + + private List<List<OMElement>> getElements(OMElement wrapper) { + List<List<OMElement>> elements = new ArrayList<List<OMElement>>(); + List<OMElement> current = new ArrayList<OMElement>(); + elements.add(current); + boolean first = true; + QName last = null; + + for (Iterator i = wrapper.getChildElements(); i.hasNext();) { + OMElement element = (OMElement)i.next(); + if (first || element.getQName().equals(last)) { + current.add(element); + last = element.getQName(); + } else { + current = new ArrayList<OMElement>(); + elements.add(current); + current.add(element); + last = element.getQName(); + } + first = false; + } + return elements; + } + + public Object getChild(OMElement wrapper, ElementInfo childElement, int index) { + Iterator children = wrapper.getChildrenWithName(childElement.getQName()); + if (!children.hasNext()) { + // No name match, try by index + List<List<OMElement>> list = getElements(wrapper); + List<OMElement> elements = list.get(index); + if (!childElement.isMany()) { + return elements.isEmpty() ? null : attachXSIType(childElement, elements.get(0)); + } else { + Object[] array = elements.toArray(); + for (Object item : array) { + attachXSIType(childElement, (OMElement)item); + } + return array; + } + } + if (!childElement.isMany()) { + if (children.hasNext()) { + OMElement child = (OMElement)children.next(); + attachXSIType(childElement, child); + return child; + } else { + return null; + } + } else { + List<OMElement> elements = new ArrayList<OMElement>(); + for (; children.hasNext();) { + OMElement child = (OMElement)children.next(); + attachXSIType(childElement, child); + elements.add(child); + } + return elements.toArray(); + } + } + + /** + * Create xis:type if required + * @param childElement + * @param element + * @return + */ + private OMElement attachXSIType(ElementInfo childElement, OMElement element) { + TypeInfo type = childElement.getType(); + if (type != null && type.getQName() != null) { + OMAttribute attr = element.getAttribute(XSI_TYPE_QNAME); + if (attr == null) { + String typeNS = type.getQName().getNamespaceURI(); + if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(typeNS)) { + return element; + } + OMNamespace ns = element.getOMFactory().createOMNamespace(typeNS, "_typens_"); + element.declareNamespace(ns); + OMNamespace xsiNS = + element.getOMFactory().createOMNamespace(XSI_TYPE_QNAME.getNamespaceURI(), + XSI_TYPE_QNAME.getPrefix()); + element.declareNamespace(xsiNS); + attr = + element.getOMFactory().createOMAttribute("type", + xsiNS, + "_typens_:" + type.getQName().getLocalPart()); + element.addAttribute(attr); + } + } + return element; + } + + private void attachXSINil(OMElement element) { + OMNamespace xsiNS = + element.getOMFactory().createOMNamespace(XSI_TYPE_QNAME.getNamespaceURI(), XSI_TYPE_QNAME.getPrefix()); + element.declareNamespace(xsiNS); + OMAttribute attr = element.getOMFactory().createOMAttribute("nil", xsiNS, "true"); + element.addAttribute(attr); + } +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Object2OMElement.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Object2OMElement.java new file mode 100644 index 0000000000..88d6b462c1 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/Object2OMElement.java @@ -0,0 +1,63 @@ +/* + * 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.databinding.axiom; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMAttribute; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.Java2SimpleTypeTransformer; + +/** + * Transformer to convert data from an simple OMElement to Java Object + * + * @version $Rev$ $Date$ + */ +public class Object2OMElement extends Java2SimpleTypeTransformer<OMElement> { + + private OMFactory factory; + + public Object2OMElement() { + super(); + factory = OMAbstractFactory.getOMFactory(); + } + + @Override + protected OMElement createElement(QName element, String text, TransformationContext context) { + OMElement omElement = AxiomHelper.createOMElement(factory, element); + if (text == null) { + OMNamespace xsi = factory.createOMNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi"); + OMAttribute nil = factory.createOMAttribute("nil", xsi, "true"); + omElement.addAttribute(nil); + } else { + factory.createOMText(omElement, text); + } + return omElement; + } + + @Override + public Class getTargetType() { + return OMElement.class; + } + +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/String2OMElement.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/String2OMElement.java new file mode 100644 index 0000000000..9eccd52d74 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/String2OMElement.java @@ -0,0 +1,64 @@ +/* + * 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.databinding.axiom; + +import java.io.ByteArrayInputStream; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * + * @version $Rev$ $Date$ + */ +public class String2OMElement extends BaseTransformer<String, OMElement> implements + PullTransformer<String, OMElement> { + + @SuppressWarnings("unchecked") + public OMElement transform(String source, TransformationContext context) { + try { + StAXOMBuilder builder = new StAXOMBuilder(new ByteArrayInputStream(source.getBytes())); + OMElement element = builder.getDocumentElement(); + AxiomHelper.adjustElementName(context, element); + return element; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<OMElement> getTargetType() { + return OMElement.class; + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/XMLStreamReader2OMElement.java b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/XMLStreamReader2OMElement.java new file mode 100644 index 0000000000..761185c297 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/java/org/apache/tuscany/sca/databinding/axiom/XMLStreamReader2OMElement.java @@ -0,0 +1,70 @@ +/* + * 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.databinding.axiom; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2OMElement extends BaseTransformer<XMLStreamReader, OMElement> implements + PullTransformer<XMLStreamReader, OMElement> { + + public XMLStreamReader2OMElement() { + super(); + } + + public OMElement transform(XMLStreamReader source, TransformationContext context) { + if (source == null) { + return null; + } + try { + StAXOMBuilder builder = new StAXOMBuilder(source); + OMElement element = builder.getDocumentElement(); + AxiomHelper.adjustElementName(context, element); + return element; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<OMElement> getTargetType() { + return OMElement.class; + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..2e94116177 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,20 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.axiom.AxiomDataBinding;type=org.apache.axiom.om.OMElement,name=axiom + diff --git a/branches/sca-android/modules/databinding-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..a1f18f9638 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,30 @@ +# 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.
+
+# Implementation classes for the transformers
+# org.apache.tuscany.sca.databinding.axiom.CallableReference2OMElement;source=org.osoa.sca.CallableReference,target=org.apache.axiom.om.OMElement,weight=10
+# org.apache.tuscany.sca.databinding.axiom.OMElement2CallableReference;source=org.apache.axiom.om.OMElement,target=org.osoa.sca.CallableReference,weight=10
+org.apache.tuscany.sca.databinding.axiom.Externalizable2OMElement;source=java.io.Externalizable,target=org.apache.axiom.om.OMElement,weight=10
+org.apache.tuscany.sca.databinding.axiom.OMElement2Externalizable;source=org.apache.axiom.om.OMElement,target=java.io.Externalizable,weight=10
+org.apache.tuscany.sca.databinding.axiom.Exception2OMElement;source=java:exception,target=org.apache.axiom.om.OMElement,weight=10
+org.apache.tuscany.sca.databinding.axiom.OMElement2Exception;source=org.apache.axiom.om.OMElement,target=java:exception,weight=10
+# org.apache.tuscany.sca.databinding.axiom.Object2OMElement;source=java:simpleType,target=org.apache.axiom.om.OMElement,weight=80000
+# org.apache.tuscany.sca.databinding.axiom.OMElement2Object;source=org.apache.axiom.om.OMElement,target=java:simpleType,weight=80000
+org.apache.tuscany.sca.databinding.axiom.OMElement2String;source=org.apache.axiom.om.OMElement,target=java.lang.String,weight=80
+org.apache.tuscany.sca.databinding.axiom.OMElement2XMLStreamReader;source=org.apache.axiom.om.OMElement,target=javax.xml.stream.XMLStreamReader,weight=60
+org.apache.tuscany.sca.databinding.axiom.String2OMElement;source=java.lang.String,target=org.apache.axiom.om.OMElement,weight=80
+org.apache.tuscany.sca.databinding.axiom.XMLStreamReader2OMElement;source=javax.xml.stream.XMLStreamReader,target=org.apache.axiom.om.OMElement,weight=60
diff --git a/branches/sca-android/modules/databinding-axiom/src/test/java/org/apache/tuscany/sca/databinding/axiom/OMElementTestCase.java b/branches/sca-android/modules/databinding-axiom/src/test/java/org/apache/tuscany/sca/databinding/axiom/OMElementTestCase.java new file mode 100644 index 0000000000..7453cb787a --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/test/java/org/apache/tuscany/sca/databinding/axiom/OMElementTestCase.java @@ -0,0 +1,129 @@ +/* + * 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.databinding.axiom; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.axiom.om.OMAttribute; +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * + * @version $Rev$ $Date$ + */ +public class OMElementTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + public final void testStringTransform() { + String2OMElement t1 = new String2OMElement(); + OMElement element = t1.transform(IPO_XML, null); + OMElement2String t2 = new OMElement2String(); + String xml = t2.transform(element, null); + Assert.assertNotNull(xml); + Assert.assertNotNull(xml.indexOf("<ipo:comment>") != -1); + } + + public final void testStringTransform2() { + String str = + "<p0:firstName xmlns:xml=\"http://www.w3.org/XML/1998/namespace\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + + "xmlns:p0=\"http://helloworld\">Robert</p0:firstName>"; + String2OMElement t1 = new String2OMElement(); + OMElement element = t1.transform(str, null); + OMElement2String t2 = new OMElement2String(); + String xml = t2.transform(element, null); + Assert.assertNotNull(xml); + Assert.assertNotNull(xml.indexOf("<ipo:comment>") != -1); + } + + public final void testStAXTransform() { + String2OMElement t1 = new String2OMElement(); + OMElement element = t1.transform(IPO_XML, null); + + OMElement2XMLStreamReader t2 = new OMElement2XMLStreamReader(); + XMLStreamReader reader = t2.transform(element, null); + + XMLStreamReader2OMElement t3 = new XMLStreamReader2OMElement(); + OMElement element2 = t3.transform(reader, null); + + Assert.assertEquals(element2.getQName(), element.getQName()); + Assert.assertEquals(new QName("http://www.example.com/IPO", "purchaseOrder"), element2.getQName()); + } + + public final void testCopy() { + String2OMElement t1 = new String2OMElement(); + OMElement element = t1.transform(IPO_XML, null); + OMElement copy = (OMElement)new AxiomDataBinding().copy(element, null, null); + assertNotSame(element, copy); + assertEquals(new QName("http://www.example.com/IPO", "purchaseOrder"), copy.getQName()); + } + + private static final QName XSI_NIL = new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi"); + + public final void testNil() { + Object2OMElement t1 = new Object2OMElement(); + TransformationContext context = new TransformationContextImpl(); + DataType<XMLType> dataType = + new DataTypeImpl<XMLType>(int.class, new XMLType(new QName("http://ns1", "nilElement"), + SimpleTypeMapperImpl.XSD_INT)); + context.setTargetDataType(dataType); + OMElement element = t1.transform(null, context); + OMAttribute attribute = element.getAttribute(XSI_NIL); + Assert.assertNotNull(attribute); + Assert.assertEquals("true", attribute.getAttributeValue()); + } + +} diff --git a/branches/sca-android/modules/databinding-axiom/src/test/resources/ipo.xml b/branches/sca-android/modules/databinding-axiom/src/test/resources/ipo.xml new file mode 100644 index 0000000000..df901d183d --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/test/resources/ipo.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<ipo:purchaseOrder + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ipo="http://www.example.com/IPO" + xsi:schemaLocation="http://www.example.com/IPO ipo.xsd" + orderDate="1999-12-01"> + + <shipTo exportCode="1" xsi:type="ipo:UKAddress"> + <name>Helen Zoe</name> + <street>47 Eden Street</street> + <city>Cambridge</city> + <postcode>CB1 1JR</postcode> + </shipTo> + + <billTo xsi:type="ipo:USAddress"> + <name>Robert Smith</name> + <street>8 Oak Avenue</street> + <city>Old Town</city> + <state>PA</state> + <zip>95819</zip> + </billTo> + + <items> + <item partNum="833-AA"> + <productName>Lapis necklace</productName> + <quantity>1</quantity> + <USPrice>99.95</USPrice> + <ipo:comment>Want this for the holidays</ipo:comment> + <shipDate>1999-12-05</shipDate> + </item> + </items> +</ipo:purchaseOrder> + diff --git a/branches/sca-android/modules/databinding-axiom/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-axiom/src/test/resources/ipo.xsd new file mode 100755 index 0000000000..af1e73172d --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/test/resources/ipo.xsd @@ -0,0 +1,137 @@ +<!-- + * 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. +--> + +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-axiom/src/test/resources/order.wsdl b/branches/sca-android/modules/databinding-axiom/src/test/resources/order.wsdl new file mode 100644 index 0000000000..a5ead60382 --- /dev/null +++ b/branches/sca-android/modules/databinding-axiom/src/test/resources/order.wsdl @@ -0,0 +1,76 @@ +<?xml version="1.0"?>
+<!--
+ * 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.
+-->
+<definitions name="StockQuote" targetNamespace="http://example.com/order.wsdl" xmlns:tns="http://example.com/order.wsdl"
+ xmlns:xsd1="http://example.com/order.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://schemas.xmlsoap.org/wsdl/">
+
+ <types>
+ <schema targetNamespace="http://example.com/order.xsd" xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+ <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd"/>
+ <element name="checkOrderStatus">
+ <complexType>
+ <sequence>
+ <element name="customerId" type="string" />
+ <element name="order" type="ipo:PurchaseOrderType" />
+ <element name="flag" type="int" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="checkOrderStatusResponse">
+ <complexType>
+ <sequence>
+ <element name="status" type="string" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="note" type="string" />
+ </schema>
+ </types>
+
+ <message name="CheckOrderStatusInput1">
+ <part name="body" element="xsd1:checkOrderStatus" />
+ </message>
+
+ <message name="CheckOrderStatusOutput1">
+ <part name="body" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <message name="CheckOrderStatusInput2">
+ <part name="p1" element="xsd1:checkOrderStatus" />
+ <part name="p2" element="xsd1:note" />
+ </message>
+
+ <message name="CheckOrderStatusOutput2">
+ <part name="p1" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <portType name="OrderPortType">
+ <operation name="checkOrderStatus">
+ <input message="tns:CheckOrderStatusInput1" />
+ <output message="tns:CheckOrderStatusOutput1" />
+ </operation>
+ <operation name="checkOrderStatus2">
+ <input message="tns:CheckOrderStatusInput2" />
+ <output message="tns:CheckOrderStatusOutput2" />
+ </operation>
+ </portType>
+
+</definitions>
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-fastinfoset/LICENSE b/branches/sca-android/modules/databinding-fastinfoset/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/branches/sca-android/modules/databinding-fastinfoset/NOTICE b/branches/sca-android/modules/databinding-fastinfoset/NOTICE new file mode 100644 index 0000000000..d83ebbe236 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/NOTICE @@ -0,0 +1,14 @@ +${pom.name} +Copyright (c) 2005 - 2006 The Apache Software Foundation + +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-fastinfoset/pom.xml b/branches/sca-android/modules/databinding-fastinfoset/pom.xml new file mode 100644 index 0000000000..3c060bf213 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/pom.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-fastinfoset</artifactId> + <name>Apache Tuscany Data Binding for FastInfoset</name> + <description>Tuscany FastInfoset Data Binding</description> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>com.sun.xml.fastinfoset</groupId> + <artifactId>FastInfoset</artifactId> + <version>1.2.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.1</version> + </dependency> + </dependencies> + <repositories> + <repository> + <snapshots> + <enabled>true</enabled> + </snapshots> + <id>java.net</id> + <name>java.net Maven 1.x Repository</name> + <url>http://download.java.net/maven/1</url> + <layout>legacy</layout> + </repository> + </repositories> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.fastinfoset</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.fastinfoset*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2Node.java b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2Node.java new file mode 100644 index 0000000000..2e0aa629f3 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2Node.java @@ -0,0 +1,70 @@ +/* + * 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.databinding.fastinfoset; + +import java.io.InputStream; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import com.sun.xml.fastinfoset.dom.DOMDocumentParser; + +/** + * @version $Rev$ $Date$ + */ +public class FastInfoset2Node extends BaseTransformer<InputStream, Node> implements + PullTransformer<InputStream, Node> { + + @Override + protected Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + public Node transform(InputStream source, TransformationContext context) { + try { + DOMDocumentParser parser = new DOMDocumentParser(); + Document doc = DOMHelper.newDocument(); + parser.parse(doc, source); + return doc.getDocumentElement(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 20; + } + + @Override + public String getSourceDataBinding() { + return "xml:fastinfoset:java.io.InputStream"; + } +} diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2SAX.java b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2SAX.java new file mode 100644 index 0000000000..77f6b77636 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2SAX.java @@ -0,0 +1,71 @@ +/* + * 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.databinding.fastinfoset; + +import java.io.InputStream; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; + +import com.sun.xml.fastinfoset.sax.SAXDocumentParser; + +/** + * @version $Rev$ $Date$ + */ +public class FastInfoset2SAX extends BaseTransformer<InputStream, ContentHandler> implements + PushTransformer<InputStream, ContentHandler> { + + @Override + protected Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, java.lang.Object, org.apache.tuscany.sca.databinding.TransformationContext) + */ + public void transform(InputStream source, ContentHandler target, TransformationContext context) { + try { + SAXDocumentParser parser = new SAXDocumentParser(); + parser.setContentHandler(target); + parser.parse(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 20; + } + + @Override + public String getSourceDataBinding() { + return "xml:fastinfoset:java.io.InputStream"; + } +} diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2XMLStreamReader.java b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2XMLStreamReader.java new file mode 100644 index 0000000000..73d549f4f8 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfoset2XMLStreamReader.java @@ -0,0 +1,67 @@ +/* + * 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.databinding.fastinfoset; + +import java.io.InputStream; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +import com.sun.xml.fastinfoset.stax.StAXDocumentParser; + +/** + * @version $Rev$ $Date$ + */ +public class FastInfoset2XMLStreamReader extends BaseTransformer<InputStream, XMLStreamReader> implements + PullTransformer<InputStream, XMLStreamReader> { + + @Override + protected Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + public XMLStreamReader transform(InputStream source, TransformationContext context) { + try { + StAXDocumentParser parser = new StAXDocumentParser(source); + return parser; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 20; + } + + @Override + public String getSourceDataBinding() { + return "xml:fastinfoset:java.io.InputStream"; + } +} diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/Node2FastInfoset.java b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/Node2FastInfoset.java new file mode 100644 index 0000000000..1c12a5dcad --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/Node2FastInfoset.java @@ -0,0 +1,71 @@ +/* + * 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.databinding.fastinfoset; + +import java.io.OutputStream; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +import com.sun.xml.fastinfoset.dom.DOMDocumentSerializer; + +/** + * @version $Rev$ $Date$ + */ +public class Node2FastInfoset extends BaseTransformer<Node, OutputStream> implements + PushTransformer<Node, OutputStream> { + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<OutputStream> getTargetType() { + return OutputStream.class; + } + + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, java.lang.Object, org.apache.tuscany.sca.databinding.TransformationContext) + */ + public void transform(Node source, OutputStream target, TransformationContext context) { + try { + DOMDocumentSerializer serializer = new DOMDocumentSerializer(); + serializer.setOutputStream(target); + serializer.serialize(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 20; + } + + @Override + public String getTargetDataBinding() { + return "xml:fastinfoset:java.io.OutputStream"; + } +} diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/XMLInputStream2FastInfoset.java b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/XMLInputStream2FastInfoset.java new file mode 100644 index 0000000000..b0d56b3bb6 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/XMLInputStream2FastInfoset.java @@ -0,0 +1,89 @@ +/* + * 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.databinding.fastinfoset; + +import java.io.InputStream; +import java.io.OutputStream; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +import com.sun.xml.fastinfoset.sax.SAXDocumentSerializer; + +/** + * @version $Rev$ $Date$ + */ +public class XMLInputStream2FastInfoset extends BaseTransformer<InputStream, OutputStream> implements + PushTransformer<InputStream, OutputStream> { + + @Override + protected Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + protected Class<OutputStream> getTargetType() { + return OutputStream.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, java.lang.Object, org.apache.tuscany.sca.databinding.TransformationContext) + */ + public void transform(InputStream source, OutputStream target, TransformationContext context) { + try { + + // Create Fast Infoset SAX serializer + SAXDocumentSerializer saxDocumentSerializer = new SAXDocumentSerializer(); + // Set the output stream + saxDocumentSerializer.setOutputStream(target); + + // Instantiate JAXP SAX parser factory + SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + /* Set parser to be namespace aware + * Very important to do otherwise invalid FI documents will be + * created by the SAXDocumentSerializer + */ + saxParserFactory.setNamespaceAware(true); + // Instantiate the JAXP SAX parser + SAXParser saxParser = saxParserFactory.newSAXParser(); + // Set the lexical handler + saxParser.setProperty("http://xml.org/sax/properties/lexical-handler", saxDocumentSerializer); + // Parse the XML document and convert to a fast infoset document + saxParser.parse(source, saxDocumentSerializer); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 20; + } + + @Override + public String getTargetDataBinding() { + return "xml:fastinfoset:java.io.OutputStream"; + } +} diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/XMLStreamReader2FastInfoset.java b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/XMLStreamReader2FastInfoset.java new file mode 100644 index 0000000000..d18206600c --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/java/org/apache/tuscany/sca/databinding/fastinfoset/XMLStreamReader2FastInfoset.java @@ -0,0 +1,75 @@ +/* + * 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.databinding.fastinfoset; + +import java.io.OutputStream; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.xml.XMLStreamSerializer; + +import com.sun.xml.fastinfoset.stax.StAXDocumentSerializer; + +/** + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2FastInfoset extends BaseTransformer<XMLStreamReader, OutputStream> implements + PushTransformer<XMLStreamReader, OutputStream> { + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + protected Class<OutputStream> getTargetType() { + return OutputStream.class; + } + + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, java.lang.Object, org.apache.tuscany.sca.databinding.TransformationContext) + */ + public void transform(XMLStreamReader source, OutputStream target, TransformationContext context) { + try { + StAXDocumentSerializer serializer = new StAXDocumentSerializer(target); + XMLStreamSerializer streamSerializer = new XMLStreamSerializer(); + streamSerializer.serialize(source, serializer); + serializer.flush(); + source.close(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 20; + } + + @Override + public String getTargetDataBinding() { + return "xml:fastinfoset:java.io.OutputStream"; + } +} diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-fastinfoset/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..ea47ee7191 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,22 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.fastinfoset.FastInfoset2Node;source=xml:fastinfoset:java.io.InputStream,target=org.w3c.dom.Node,weight=100 +org.apache.tuscany.sca.databinding.fastinfoset.FastInfoset2XMLStreamReader;source=xml:fastinfoset:java.io.InputStream,target=javax.xml.stream.XMLStreamReader,weight=80 + + diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer b/branches/sca-android/modules/databinding-fastinfoset/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer new file mode 100644 index 0000000000..1610b4f54d --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer @@ -0,0 +1,22 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.fastinfoset.FastInfoset2SAX;source=xml:fastinfoset:java.io.InputStream,target=org.xml.sax.ContentHandler ,weight=80 +org.apache.tuscany.sca.databinding.fastinfoset.Node2FastInfoset;source=org.w3c.dom.Node,target=xml:fastinfoset:java.io.OutputStream,weight=100 +org.apache.tuscany.sca.databinding.fastinfoset.XMLInputStream2FastInfoset;source=java.io.InputStream,target=xml:fastinfoset:java.io.OutputStream,weight=120 +org.apache.tuscany.sca.databinding.fastinfoset.XMLStreamReader2FastInfoset;source=javax.xml.stream.XMLStreamReader,target=xml:fastinfoset:java.io.OutputStream,weight=70 diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/test/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfosetTransformerTestCase.java b/branches/sca-android/modules/databinding-fastinfoset/src/test/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfosetTransformerTestCase.java new file mode 100644 index 0000000000..bb8adf39be --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/test/java/org/apache/tuscany/sca/databinding/fastinfoset/FastInfosetTransformerTestCase.java @@ -0,0 +1,127 @@ +/* + * 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.databinding.fastinfoset; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.StringReader; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.xml.InputStream2Node; +import org.apache.tuscany.sca.databinding.xml.Node2OutputStream; +import org.apache.tuscany.sca.databinding.xml.Node2String; +import org.w3c.dom.Node; + +/** + * + * @version $Rev$ $Date$ + */ +public class FastInfosetTransformerTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + public void testXML2FastInfoset() throws Exception { + XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(IPO_XML)); + XMLStreamReader2FastInfoset t1 = new XMLStreamReader2FastInfoset(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + t1.transform(reader, bos, null); + // System.out.println(bos.toString()); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + FastInfoset2Node t2 = new FastInfoset2Node(); + Node node = t2.transform(bis, null); + String xml = new Node2String().transform(node, null); + + // System.out.println(xml); + + } + + public void testPerf() throws Exception { + byte[] str = IPO_XML.getBytes(); + ByteArrayInputStream bis = new ByteArrayInputStream(str); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLInputStream2FastInfoset t = new XMLInputStream2FastInfoset(); + t.transform(bis, bos, null); + byte[] fast = bos.toByteArray(); + System.out.println(str.length + ".vs." + fast.length); + + long d1 = 0L; + long d2 = 0L; + for (int i = 0; i < 100; i++) { + InputStream2Node t1 = new InputStream2Node(); + FastInfoset2Node t2 = new FastInfoset2Node(); + InputStream is1 = new ByteArrayInputStream(str); + InputStream is2 = new ByteArrayInputStream(fast); + long s1 = System.currentTimeMillis(); + Node n1 = t1.transform(is1, null); + long s2 = System.currentTimeMillis(); + Node n2 = t2.transform(is2, null); + long s3 = System.currentTimeMillis(); + d1 += s2 - s1; // from plain xml + d2 += s3 - s2; // from fastinfoset + Node2OutputStream t3 = new Node2OutputStream(); + Node2FastInfoset t4 = new Node2FastInfoset(); + ByteArrayOutputStream os1 = new ByteArrayOutputStream(); + ByteArrayOutputStream os2 = new ByteArrayOutputStream(); + long s4 = System.currentTimeMillis(); + t3.transform(n1, os1, null); + long s5 = System.currentTimeMillis(); + t4.transform(n2, os2, null); + long s6 = System.currentTimeMillis(); + d1 += s5 - s4; // to plain xml + d2 += s6 - s5; // to fastinfoset + } + System.out.println("POX " + d1 + ".vs. FIS " + d2); + } + +} diff --git a/branches/sca-android/modules/databinding-fastinfoset/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-fastinfoset/src/test/resources/ipo.xsd new file mode 100644 index 0000000000..5a493e1746 --- /dev/null +++ b/branches/sca-android/modules/databinding-fastinfoset/src/test/resources/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/LICENSE b/branches/sca-android/modules/databinding-jaxb-axiom/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/NOTICE b/branches/sca-android/modules/databinding-jaxb-axiom/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/NOTICE @@ -0,0 +1,6 @@ +${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/pom.xml b/branches/sca-android/modules/databinding-jaxb-axiom/pom.xml new file mode 100644 index 0000000000..12150abb7e --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/pom.xml @@ -0,0 +1,189 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-jaxb-axiom</artifactId> + <name>Apache Tuscany SCA Data Binding for JAXB-AXIOM</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding-jaxb</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-api</artifactId> + <version>1.2.5</version> + <exclusions> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + <exclusion> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + </exclusion> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + <exclusion> + <groupId>xml-apis</groupId> + <artifactId>xml-apis</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-impl</artifactId> + <version>1.2.5</version> + <scope>runtime</scope> + </dependency> + </dependencies> + + <repositories> + <repository> + <snapshots> + <enabled>true</enabled> + </snapshots> + <id>java.net</id> + <name>java.net Maven 1.x Repository</name> + <url>http://download.java.net/maven/1</url> + <layout>legacy</layout> + </repository> + </repositories> + + <pluginRepositories> + <pluginRepository> + <id>java.net2</id> + <name>java.net Maven 2.x Repository</name> + <url>http://download.java.net/maven/2</url> + </pluginRepository> + </pluginRepositories> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy</id> + <phase>generate-sources</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.1</version> + <type>jar</type> + </artifactItem> + </artifactItems> + <outputDirectory>${project.build.directory}/endorsed</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine>-Djava.endorsed.dirs=target/endorsed</argLine> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.0</version> + <executions> + <execution> + <id>add-test-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>target/jaxb-source</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.jvnet.jaxb2.maven2</groupId> + <artifactId>maven-jaxb2-plugin</artifactId> + <version>0.5</version> + <executions> + <execution> + <id>generate-jaxb</id> + <phase>generate-test-sources</phase> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + <configuration> + <generatePackage>com.example.ipo.jaxb</generatePackage> + <generateDirectory>${project.build.directory}/jaxb-source</generateDirectory> + <schemaDirectory>${basedir}/src/test/resources</schemaDirectory> + <schemaIncludes> + <include>ipo.xsd</include> + </schemaIncludes> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.jaxb.axiom</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.jaxb.axiom*</Export-Package> + </instructions> + </configuration> + </plugin> + + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/AxiomHelper.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/AxiomHelper.java new file mode 100644 index 0000000000..93277e77bf --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/AxiomHelper.java @@ -0,0 +1,140 @@ +/* + * 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.databinding.jaxb.axiom; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMDataSource; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.axiom.om.OMXMLParserWrapper; +import org.apache.axiom.om.impl.builder.StAXBuilder; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Helper for AXIOM + * + * @version $Rev$ $Date$ + */ +public class AxiomHelper { + private static final String DEFAULT_PREFIX = "_ns_"; + + private AxiomHelper() { + } + + /** + * See http://issues.apache.org/jira/browse/WSCOMMONS-240 + * @param om + */ + public static void completeAndClose(OMElement om) { + // Get the builder associated with the om element + OMXMLParserWrapper builder = om.getBuilder(); + if (builder != null) { + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).releaseParserOnClose(true); + } + OMElement document = builder.getDocumentElement(); + if (document != null) { + document.build(); + } + } + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).close(); + } + } + + /** + * This method will close the builder immediately. Any subsequent Axiom objects won't + * be built or accessible. + */ + public static void closeImmediately(OMElement om) { + // Get the builder associated with the om element + OMXMLParserWrapper builder = om.getBuilder(); + if (builder != null) { + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).releaseParserOnClose(true); + ((StAXBuilder)builder).close(); + } + // builder.close(); + } + } + + /** + * @param context + * @param element + */ + public static void adjustElementName(TransformationContext context, OMElement element) { + if (context != null) { + DataType<?> dataType = context.getTargetDataType(); + Object logical = dataType == null ? null : dataType.getLogical(); + if (!(logical instanceof XMLType)) { + return; + } + XMLType xmlType = (XMLType)logical; + if (xmlType.isElement() && !xmlType.getElementName().equals(element.getQName())) { + // FIXME:: Throw exception or switch to the new Element? + OMFactory factory = OMAbstractFactory.getOMFactory(); + QName name = xmlType.getElementName(); + OMNamespace namespace = factory.createOMNamespace(name.getNamespaceURI(), name.getPrefix()); + element.setNamespace(namespace); + element.setLocalName(name.getLocalPart()); + } + } + } + + public static OMElement createOMElement(OMFactory factory, QName element) { + String localName = element.getLocalPart(); + OMNamespace ns = createOMNamespace(factory, element); + + return factory.createOMElement(localName, ns); + + } + + public static OMElement createOMElement(OMFactory factory, QName element, OMDataSource dataSource) { + String localName = element.getLocalPart(); + OMNamespace ns = createOMNamespace(factory, element); + + return factory.createOMElement(dataSource, localName, ns); + + } + + /** + * @param factory + * @param name + * @return + */ + public static OMNamespace createOMNamespace(OMFactory factory, QName name) { + String namespaceURI = name.getNamespaceURI(); + String prefix = name.getPrefix(); + + OMNamespace ns = null; + // Qualified Element: we need an OMNamespace + if (prefix.length() == 0) { + // The prefix does not appear to be specified, let's create one + prefix = DEFAULT_PREFIX; + } + ns = factory.createOMNamespace(namespaceURI, prefix); + return ns; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXB2OMElement.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXB2OMElement.java new file mode 100644 index 0000000000..c4726ad8fa --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXB2OMElement.java @@ -0,0 +1,78 @@ +/* + * 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.databinding.jaxb.axiom; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; + +/** + * JAXB Object --> AXIOM OMElement transformer + * + * @version $Rev$ $Date$ + */ +public class JAXB2OMElement extends BaseTransformer<Object, OMElement> implements PullTransformer<Object, OMElement> { + private OMFactory factory = OMAbstractFactory.getOMFactory(); + + @Override + public String getSourceDataBinding() { + return JAXBDataBinding.NAME; + } + + @SuppressWarnings("unchecked") + public OMElement transform(Object source, TransformationContext context) throws TransformationException { + JAXBContext jaxbContext; + try { + jaxbContext = JAXBContextHelper.createJAXBContext(context, true); + } catch (JAXBException e) { + throw new TransformationException(e); + } + Object element = JAXBContextHelper.createJAXBElement(jaxbContext, context.getTargetDataType(), source); + QName name = jaxbContext.createJAXBIntrospector().getElementName(element); + JAXBDataSource dataSource = new JAXBDataSource(element, jaxbContext); + OMElement omElement = AxiomHelper.createOMElement(factory, name, dataSource); + return omElement; + } + + @Override + public Class<Object> getSourceType() { + return Object.class; + } + + @Override + public Class<OMElement> getTargetType() { + return OMElement.class; + } + + @Override + public int getWeight() { + return 3000; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java new file mode 100644 index 0000000000..dd9fbfbfd0 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java @@ -0,0 +1,124 @@ +/* + * 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.databinding.jaxb.axiom; + +import java.io.OutputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.axiom.om.OMDataSource; +import org.apache.axiom.om.OMOutputFormat; +import org.apache.axiom.om.util.StAXUtils; + +/** + * + * @version $Rev$ $Date$ + */ +public class JAXBDataSource implements OMDataSource { + private JAXBContext context; + private Object element; + private Marshaller marshaller; + + public JAXBDataSource(Object element, JAXBContext context) { + this.element = element; + this.context = context; + } + + private Marshaller getMarshaller() throws JAXBException { + if (marshaller == null) { + // For thread safety, not sure we can cache the marshaller + // marshaller = JAXBContextHelper.getMarshaller(context); + marshaller = context.createMarshaller(); + } + return marshaller; + } + + public XMLStreamReader getReader() throws XMLStreamException { + // FIXME: [rfeng] This is a quick and dirty implementation + // We could use the fastinfoset to optimize the roundtrip + StringWriter writer = new StringWriter(); + serialize(writer, new OMOutputFormat()); + StringReader reader = new StringReader(writer.toString()); + return StAXUtils.createXMLStreamReader(reader); + } + + public void serialize(final XMLStreamWriter xmlWriter) throws XMLStreamException { + try { + // marshaller.setProperty(Marshaller.JAXB_ENCODING, format.getCharSetEncoding()); + AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws Exception { + Marshaller marshaller = getMarshaller(); + // Set the FRAGEMENT property to avoid duplicate XML declaration + marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); + marshaller.marshal(element, xmlWriter); + marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE); + return null; + } + }); + } catch (PrivilegedActionException e) { + throw new XMLStreamException(e.getException()); + } + } + + public void serialize(final OutputStream output, OMOutputFormat format) throws XMLStreamException { + try { + // marshaller.setProperty(Marshaller.JAXB_ENCODING, format.getCharSetEncoding()); + AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws Exception { + Marshaller marshaller = getMarshaller(); + marshaller.marshal(element, output); + return null; + } + }); + } catch (PrivilegedActionException e) { + throw new XMLStreamException(e.getException()); + } + } + + public void serialize(final Writer writer, OMOutputFormat format) throws XMLStreamException { + try { + AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws Exception { + Marshaller marshaller = getMarshaller(); + marshaller.marshal(element, writer); + return null; + } + }); + } catch (PrivilegedActionException e) { + throw new XMLStreamException(e.getException()); + } + } + + public Object getObject() { + return element; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java new file mode 100644 index 0000000000..00e99aaacd --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java @@ -0,0 +1,85 @@ +/* + * 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.databinding.jaxb.axiom; + +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; + +/** + * @version $Rev$ $Date$ + */ +public class OMElement2JAXB extends BaseTransformer<OMElement, Object> implements PullTransformer<OMElement, Object> { + + @Override + public String getSourceDataBinding() { + return org.apache.axiom.om.OMElement.class.getName(); + } + + @SuppressWarnings("unchecked") + public Object transform(final OMElement source, final TransformationContext context) throws TransformationException { + try { + return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws JAXBException, XMLStreamException { + // Marshalling directly to the output stream is faster than marshalling through the + // XMLStreamWriter. + // Take advantage of this optimization if there is an output stream. + JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + XMLStreamReader reader = source.getXMLStreamReaderWithoutCaching(); + Object result = + unmarshaller.unmarshal(reader, JAXBContextHelper.getJavaType(context.getTargetDataType())); + reader.close(); + return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result); + } + }); + } catch (PrivilegedActionException e) { + throw new TransformationException(e.getException()); + } + } + + @Override + public Class<OMElement> getSourceType() { + return OMElement.class; + } + + @Override + public Class<Object> getTargetType() { + return Object.class; + } + + @Override + public int getWeight() { + return 3000; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBCustomBuilder.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBCustomBuilder.java new file mode 100644 index 0000000000..b7a395a623 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBCustomBuilder.java @@ -0,0 +1,110 @@ +/* + * 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.databinding.jaxb.axiom.ext; + + +/** + * JAXBCustomBuilder creates an OMSourcedElement backed by a JAXBDataSource + * for the specified namespace and localPart. + */ +public class JAXBCustomBuilder +//FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 +// implements CustomBuilder +{ + + private JAXBDSContext jdsContext; + + /** + * Create a JAXBCustomBuilder + * @param context JAXBDSContext + */ + public JAXBCustomBuilder(JAXBDSContext context) { + super(); + this.jdsContext = context; + } + + // FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 + /* + public OMElement create(String namespace, + String localPart, + OMContainer parent, + XMLStreamReader reader, + OMFactory factory) throws OMException { + + // There are some situations where we want to use normal + // unmarshalling, so return null + if (!shouldUnmarshal(namespace, localPart)) { + // JAXBCustomBuilderMonitor.updateTotalFailedCreates(); + return null; + } + try { + // Create an OMSourcedElement backed by an unmarshalled JAXB object + OMNamespace ns = factory.createOMNamespace(namespace, reader.getPrefix()); + + Object jaxb = jdsContext.unmarshal(reader); + + OMDataSource ds = new JAXBDataSourceExt(jaxb, jdsContext); + OMElement omse = factory.createOMElement(ds, localPart, ns); + + parent.addChild(omse); + // JAXBCustomBuilderMonitor.updateTotalCreates(); + return omse; + } catch (JAXBException e) { + // JAXBCustomBuilderMonitor.updateTotalFailedCreates(); + throw new OMException(e); + } + } + */ + + /** + * The namespace identifier for the SOAP 1.1 envelope. + */ + public static final String URI_NS_SOAP_1_1_ENVELOPE = "http://schemas.xmlsoap.org/soap/envelope/"; + /** + * The namespace identifier for the SOAP 1.2 envelope. + */ + public static final String URI_NS_SOAP_1_2_ENVELOPE = "http://www.w3.org/2003/05/soap-envelope"; + + /** + * @param namespace + * @param localPart + * @return true if this ns and local part is acceptable for unmarshalling + */ + private boolean shouldUnmarshal(String namespace, String localPart) { + + // Don't unmarshall SOAPFaults or anything else in the SOAP + // namespace. + // Don't unmarshall elements that are unqualified + if (localPart == null || namespace == null + || namespace.length() == 0 + || URI_NS_SOAP_1_1_ENVELOPE.equals(namespace) + || URI_NS_SOAP_1_2_ENVELOPE.equals(namespace)) { + return false; + } + + // Don't unmarshal if this looks like encrypted data + if (localPart.equals("EncryptedData")) { + return false; + } + + return true; + + } +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBDSContext.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBDSContext.java new file mode 100644 index 0000000000..6fd65d4752 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBDSContext.java @@ -0,0 +1,189 @@ +/* + * 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.databinding.jaxb.axiom.ext; + +import java.io.OutputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.attachment.AttachmentMarshaller; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.axiom.om.OMException; +import org.apache.axiom.om.impl.MTOMXMLStreamWriter; +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; + +/* + * To marshal or unmarshal a JAXB object, the JAXBContext is necessary. + * In addition, access to the MessageContext and other context objects may be necessary + * to get classloader information, store attachments etc. + * + * The JAXBDSContext bundles all of this information together. + */ +public class JAXBDSContext { + + private static final Logger log = Logger.getLogger(JAXBDSContext.class.getName()); + private static final boolean DEBUG_ENABLED = log.isLoggable(Level.FINER); + + private JAXBContext jaxbContext = null; // JAXBContext + + /** + * "Dispatch" Constructor Use this full constructor when the JAXBContent is provided by the + * customer. + * + * @param jaxbContext + */ + public JAXBDSContext(JAXBContext jaxbContext) { + this.jaxbContext = jaxbContext; + } + + public JAXBContext getJAXBContext() { + return jaxbContext; + } + + /** + * Unmarshal the xml into a JAXB object + * @param reader + * @return + * @throws JAXBException + */ + public Object unmarshal(XMLStreamReader reader) throws JAXBException { + + Unmarshaller u = JAXBContextHelper.getUnmarshaller(getJAXBContext()); + + Object jaxb = null; + + // Unmarshal into the business object. + jaxb = unmarshalElement(u, reader); // preferred and always used for + // style=document + + // Successfully unmarshalled the object + // JAXBUtils.releaseJAXBUnmarshaller(getJAXBContext(cl), u); + + // Don't close the reader. The reader is owned by the caller, and it + // may contain other xml instance data (other than this JAXB object) + // reader.close(); + return jaxb; + } + + /** + * Marshal the jaxb object + * @param obj + * @param writer + * @param am AttachmentMarshaller, optional Attachment + */ + public void marshal(Object obj, XMLStreamWriter writer) throws JAXBException { + + // Very easy, use the Context to get the Marshaller. + // Use the marshaller to write the object. + Marshaller m = JAXBContextHelper.getMarshaller(getJAXBContext()); + AttachmentMarshaller am = m.getAttachmentMarshaller(); + boolean xop = am != null ? am.isXOPPackage() : false; + // Marshal the object + marshalElement(obj, m, writer, !xop); + } + + /** + * Preferred way to marshal objects. + * + * @param b Object that can be rendered as an element and the element name is known by the + * Marshaller + * @param m Marshaller + * @param writer XMLStreamWriter + */ + private static void marshalElement(final Object b, + final Marshaller m, + final XMLStreamWriter writer, + final boolean optimize) { + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + // Marshalling directly to the output stream is faster than marshalling through the + // XMLStreamWriter. + // Take advantage of this optimization if there is an output stream. + try { + OutputStream os = (optimize) ? getOutputStream(writer) : null; + if (os != null) { + writer.flush(); + m.marshal(b, os); + } else { + m.marshal(b, writer); + } + } catch (OMException e) { + throw e; + } catch (Throwable t) { + throw new OMException(t); + } + return null; + } + }); + } + + /** + * If the writer is backed by an OutputStream, then return the OutputStream + * @param writer + * @return OutputStream or null + */ + private static OutputStream getOutputStream(XMLStreamWriter writer) throws XMLStreamException { + if (writer.getClass() == MTOMXMLStreamWriter.class) { + return ((MTOMXMLStreamWriter)writer).getOutputStream(); + } + if (writer.getClass() == XMLStreamWriterWithOS.class) { + return ((XMLStreamWriterWithOS)writer).getOutputStream(); + } + return null; + } + + /** + * Preferred way to unmarshal objects + * + * @param u Unmarshaller + * @param reader XMLStreamReader + * @return Object that represents an element + */ + private static Object unmarshalElement(final Unmarshaller u, final XMLStreamReader reader) { + try { + return AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + try { + return u.unmarshal(reader); + } catch (OMException e) { + throw e; + } catch (Throwable t) { + throw new OMException(t); + } + } + }); + + } catch (OMException e) { + throw e; + } catch (Throwable t) { + throw new OMException(t); + } + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBDataSourceExt.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBDataSourceExt.java new file mode 100644 index 0000000000..7702d099b4 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/JAXBDataSourceExt.java @@ -0,0 +1,147 @@ +/* + * 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.databinding.jaxb.axiom.ext; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.bind.JAXBException; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.axiom.om.OMException; +import org.apache.axiom.om.OMOutputFormat; +import org.apache.axiom.om.impl.MTOMXMLStreamWriter; +import org.apache.axiom.om.util.StAXUtils; + +/** + * OMDataSource backed by a jaxb object + */ +public class JAXBDataSourceExt + +//FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 +// extends OMDataSourceExtBase +{ + + private static final Logger log = Logger.getLogger(JAXBDataSourceExt.class.getName()); + + private Object jaxb; + private JAXBDSContext context; + + public JAXBDataSourceExt(Object jaxb, JAXBDSContext context) { + super(); + this.jaxb = jaxb; + this.context = context; + } + + public void close() { + } + + // FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 + // public OMDataSourceExt copy() { + // return new JAXBDataSourceExt(jaxb, context); + // } + + public Object getObject() { + return jaxb; + } + + public JAXBDSContext getContext() { + return context; + } + + public XMLStreamReader getReader() throws XMLStreamException { + + try { + String encoding = "utf-8"; + InputStream is = new ByteArrayInputStream(getXMLBytes(encoding)); + return StAXUtils.createXMLStreamReader(is, encoding); + } catch (UnsupportedEncodingException e) { + throw new XMLStreamException(e); + } + } + + public void serialize(OutputStream output, OMOutputFormat format) throws XMLStreamException { + MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(output, format); + serialize(writer); + writer.flush(); + try { + writer.close(); + } catch (XMLStreamException e) { + // An exception can occur if nothing is written to the + // writer. This is possible if the underlying data source + // writers to the output stream directly. + if (log.isLoggable(Level.FINER)) { + log.finer("Catching and swallowing exception " + e); + } + } + } + + public void serialize(Writer writerTarget, OMOutputFormat format) throws XMLStreamException { + MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(StAXUtils.createXMLStreamWriter(writerTarget)); + writer.setOutputFormat(format); + serialize(writer); + writer.flush(); + writer.close(); + } + + public void serialize(XMLStreamWriter xmlWriter) throws XMLStreamException { + try { + context.marshal(jaxb, xmlWriter); + } catch (JAXBException je) { + throw new XMLStreamException(je); + } + } + + public byte[] getXMLBytes(String encoding) throws UnsupportedEncodingException { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // Exposes getOutputStream, which allows faster writes. + XMLStreamWriterWithOS writer = new XMLStreamWriterWithOS(baos, encoding); + + // Write the business object to the writer + serialize(writer); + + // Flush the writer + writer.flush(); + writer.close(); + return baos.toByteArray(); + } catch (XMLStreamException e) { + throw new OMException(e); + } + } + + public boolean isDestructiveRead() { + return false; + } + + public boolean isDestructiveWrite() { + return false; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/SourceDataSource.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/SourceDataSource.java new file mode 100644 index 0000000000..758a82f72f --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/SourceDataSource.java @@ -0,0 +1,125 @@ +/* + * 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.databinding.jaxb.axiom.ext; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.axiom.om.OMException; +import org.apache.axiom.om.util.StAXUtils; + +/** + * OMDataSource backed by a source + */ +public class SourceDataSource +// FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 +// extends OMDataSourceExtBase +{ + private Source data; + + public SourceDataSource(Source data) { + super(); + this.data = data; + } + + public void close() { + } + + // FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 + // public OMDataSourceExt copy() { + // return new SourceDataSource(data); + // } + + public Object getObject() { + return data; + } + + public XMLStreamReader getReader() throws XMLStreamException { + + try { + String encoding = "UTF-8"; + InputStream is = new ByteArrayInputStream(getXMLBytes(encoding)); + return StAXUtils.createXMLStreamReader(is, encoding); + } catch (UnsupportedEncodingException e) { + throw new XMLStreamException(e); + } + } + + public byte[] getXMLBytes(String encoding) throws UnsupportedEncodingException { + byte[] bytes = null; + try { + bytes = (byte[])null; + + if (data instanceof StreamSource) { + InputStream is = ((StreamSource)data).getInputStream(); + if (is != null) { + bytes = getBytesFromStream(is); + } + } else { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Result result = new StreamResult(out); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.transform(data, result); + bytes = out.toByteArray(); + } + } catch (OMException e) { + throw e; + } catch (UnsupportedEncodingException e) { + throw e; + } catch (Throwable e) { + throw new OMException(e); + } + + return bytes; + } + + public boolean isDestructiveRead() { + return false; + } + + public boolean isDestructiveWrite() { + return false; + } + + private static byte[] getBytesFromStream(InputStream is) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] buf = new byte[4096]; + while (true) { + int size = is.read(buf); + if (size < 0) { + break; + } + bos.write(buf, 0, size); + } + return bos.toByteArray(); + } +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/XMLStreamWriterWithOS.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/XMLStreamWriterWithOS.java new file mode 100644 index 0000000000..44e34c3647 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/XMLStreamWriterWithOS.java @@ -0,0 +1,246 @@ +/* + * 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.databinding.jaxb.axiom.ext; + +import java.io.OutputStream; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.axiom.om.util.StAXUtils; + +/** + * XMLStreamReader that exposes direct access to the OutputStream. + * Writing to the output stream is faster in some cases. + */ +public class XMLStreamWriterWithOS implements XMLStreamWriter { + private XMLStreamWriter writer; + private String charSetEncoding; + private OutputStream os; + + public XMLStreamWriterWithOS(OutputStream os, String charSetEncoding) throws XMLStreamException { + super(); + writer = null; // Writer is created when needed + this.os = os; + this.charSetEncoding = charSetEncoding; + } + + /** + * The writer is created lazily. + * If only the output stream is used, then the writer is never created. + */ + private void createWriter() throws XMLStreamException { + if (writer == null) { + writer = StAXUtils.createXMLStreamWriter(os, charSetEncoding); + } + } + + public void close() throws XMLStreamException { + if (writer != null) { + writer.close(); + } + } + + public void flush() throws XMLStreamException { + if (writer != null) { + writer.flush(); + } + } + + public NamespaceContext getNamespaceContext() { + try { + createWriter(); + } catch (Exception e) { + throw new RuntimeException(e); + } + return writer.getNamespaceContext(); + } + + public String getPrefix(String arg0) throws XMLStreamException { + createWriter(); + return writer.getPrefix(arg0); + } + + public Object getProperty(String arg0) throws IllegalArgumentException { + try { + createWriter(); + } catch (XMLStreamException e) { + throw new IllegalArgumentException(e); + } + return writer.getProperty(arg0); + } + + public void setDefaultNamespace(String arg0) throws XMLStreamException { + createWriter(); + writer.setDefaultNamespace(arg0); + } + + public void setNamespaceContext(NamespaceContext arg0) throws XMLStreamException { + createWriter(); + writer.setNamespaceContext(arg0); + } + + public void setPrefix(String arg0, String arg1) throws XMLStreamException { + createWriter(); + writer.setPrefix(arg0, arg1); + } + + public void writeAttribute(String arg0, String arg1, String arg2, String arg3) throws XMLStreamException { + createWriter(); + writer.writeAttribute(arg0, arg1, arg2, arg3); + } + + public void writeAttribute(String arg0, String arg1, String arg2) throws XMLStreamException { + createWriter(); + writer.writeAttribute(arg0, arg1, arg2); + } + + public void writeAttribute(String arg0, String arg1) throws XMLStreamException { + createWriter(); + writer.writeAttribute(arg0, arg1); + } + + public void writeCData(String arg0) throws XMLStreamException { + createWriter(); + writer.writeCData(arg0); + } + + public void writeCharacters(char[] arg0, int arg1, int arg2) throws XMLStreamException { + createWriter(); + writer.writeCharacters(arg0, arg1, arg2); + } + + public void writeCharacters(String arg0) throws XMLStreamException { + createWriter(); + writer.writeCharacters(arg0); + } + + public void writeComment(String arg0) throws XMLStreamException { + createWriter(); + writer.writeComment(arg0); + } + + public void writeDefaultNamespace(String arg0) throws XMLStreamException { + createWriter(); + writer.writeDefaultNamespace(arg0); + } + + public void writeDTD(String arg0) throws XMLStreamException { + createWriter(); + writer.writeDTD(arg0); + } + + public void writeEmptyElement(String arg0, String arg1, String arg2) throws XMLStreamException { + createWriter(); + writer.writeEmptyElement(arg0, arg1, arg2); + } + + public void writeEmptyElement(String arg0, String arg1) throws XMLStreamException { + createWriter(); + writer.writeEmptyElement(arg0, arg1); + } + + public void writeEmptyElement(String arg0) throws XMLStreamException { + createWriter(); + writer.writeEmptyElement(arg0); + } + + public void writeEndDocument() throws XMLStreamException { + createWriter(); + writer.writeEndDocument(); + } + + public void writeEndElement() throws XMLStreamException { + createWriter(); + writer.writeEndElement(); + } + + public void writeEntityRef(String arg0) throws XMLStreamException { + createWriter(); + writer.writeEntityRef(arg0); + } + + public void writeNamespace(String arg0, String arg1) throws XMLStreamException { + createWriter(); + writer.writeNamespace(arg0, arg1); + } + + public void writeProcessingInstruction(String arg0, String arg1) throws XMLStreamException { + createWriter(); + writer.writeProcessingInstruction(arg0, arg1); + } + + public void writeProcessingInstruction(String arg0) throws XMLStreamException { + createWriter(); + writer.writeProcessingInstruction(arg0); + } + + public void writeStartDocument() throws XMLStreamException { + createWriter(); + writer.writeStartDocument(); + } + + public void writeStartDocument(String arg0, String arg1) throws XMLStreamException { + createWriter(); + writer.writeStartDocument(arg0, arg1); + } + + public void writeStartDocument(String arg0) throws XMLStreamException { + createWriter(); + writer.writeStartDocument(arg0); + } + + public void writeStartElement(String arg0, String arg1, String arg2) throws XMLStreamException { + createWriter(); + writer.writeStartElement(arg0, arg1, arg2); + } + + public void writeStartElement(String arg0, String arg1) throws XMLStreamException { + createWriter(); + writer.writeStartElement(arg0, arg1); + } + + public void writeStartElement(String arg0) throws XMLStreamException { + createWriter(); + writer.writeStartElement(arg0); + } + + /** + * If this XMLStreamWriter is connected to an OutputStream + * then the OutputStream is returned. This allows a node + * (perhaps an OMSourcedElement) to write its content + * directly to the OutputStream. + * @return OutputStream or null + */ + public OutputStream getOutputStream() throws XMLStreamException { + + if (os != null) { + // Flush the state of the writer..Many times the + // write defers the writing of tag characters (>) + // until the next write. Flush out this character + if (writer != null) { + this.writeCharacters(""); + this.flush(); + } + } + return os; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/XMLStringDataSource.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/XMLStringDataSource.java new file mode 100644 index 0000000000..a2a68c8eb0 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/ext/XMLStringDataSource.java @@ -0,0 +1,88 @@ +/* + * 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.databinding.jaxb.axiom.ext; + +import java.io.IOException; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.io.Writer; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.axiom.om.OMOutputFormat; +import org.apache.axiom.om.util.StAXUtils; + +/** + * OMDataSource backed by a string containing xml data + */ +// FIXME: To be refectored into databinding-axiom +public class XMLStringDataSource + +//FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 +// extends OMDataSourceExtBase +{ + private String data; + + public XMLStringDataSource(String data) { + super(); + this.data = data; + } + + public void close() { + } + + // FIXME: [rfeng] Re-enable it after we move to AXIOM 1.2.7 + // public OMDataSourceExt copy() { + // return new XMLStringDataSource(data); + // } + + public Object getObject() { + return data; + } + + public XMLStreamReader getReader() throws XMLStreamException { + StringReader reader = new StringReader(data); + return StAXUtils.createXMLStreamReader(reader); + } + + public void serialize(Writer writer, OMOutputFormat format) throws XMLStreamException { + try { + writer.write(data); + } catch (UnsupportedEncodingException e) { + throw new XMLStreamException(e); + } catch (IOException e) { + throw new XMLStreamException(e); + } + } + + public byte[] getXMLBytes(String encoding) throws UnsupportedEncodingException { + return data.getBytes(encoding); + } + + public boolean isDestructiveRead() { + return false; + } + + public boolean isDestructiveWrite() { + return false; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..b48e629927 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,26 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.jaxb.axiom.JAXB2OMElement;source=javax.xml.bind.JAXBElement,target=org.apache.axiom.om.OMElement,weight=3000 +org.apache.tuscany.sca.databinding.jaxb.axiom.JAXB2OMElement;source=java:simpleType,target=org.apache.axiom.om.OMElement,weight=3000 +org.apache.tuscany.sca.databinding.jaxb.axiom.JAXB2OMElement;source=java:complexType,target=org.apache.axiom.om.OMElement,weight=3000 + +org.apache.tuscany.sca.databinding.jaxb.axiom.OMElement2JAXB;source=org.apache.axiom.om.OMElement,target=javax.xml.bind.JAXBElement,weight=3000,public=false +org.apache.tuscany.sca.databinding.jaxb.axiom.OMElement2JAXB;source=org.apache.axiom.om.OMElement,target=java:complexType,weight=90000,public=false +org.apache.tuscany.sca.databinding.jaxb.axiom.OMElement2JAXB;source=org.apache.axiom.om.OMElement,target=java:simpleType,weight=90000,public=false + diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/test/java/org/apache/tuscany/databinding/jaxb/axiom/JAXB2OMTestCase.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/test/java/org/apache/tuscany/databinding/jaxb/axiom/JAXB2OMTestCase.java new file mode 100644 index 0000000000..543a76594f --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/test/java/org/apache/tuscany/databinding/jaxb/axiom/JAXB2OMTestCase.java @@ -0,0 +1,109 @@ +/* + * 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.databinding.jaxb.axiom; + +import java.io.StringWriter; + +import javax.xml.bind.JAXBElement; +import javax.xml.stream.XMLStreamReader; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.databinding.jaxb.JAXB2Node; +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; +import org.apache.tuscany.sca.databinding.jaxb.axiom.JAXB2OMElement; +import org.apache.tuscany.sca.databinding.xml.Node2XMLStreamReader; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.junit.Test; +import org.w3c.dom.Node; + +import com.example.ipo.jaxb.ObjectFactory; +import com.example.ipo.jaxb.PurchaseOrderType; +import com.example.ipo.jaxb.USAddress; +import com.example.ipo.jaxb.USState; + +/** + * @version $Rev$ $Date$ + */ +public class JAXB2OMTestCase { + @Test + public void testTransformElement() throws Exception { + JAXBElement<PurchaseOrderType> po = createPO(); + DataType<?> sourceDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, XMLType.UNKNOWN); + DataType<?> targetDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, new XMLType(po.getName(), null)); + TransformationContext tContext = new TransformationContextImpl(); + tContext.setSourceDataType(sourceDataType); + tContext.setTargetDataType(targetDataType); + + // Force the JAXBContext to be cached + JAXBContextHelper.createJAXBContext(tContext, true); + + long start = System.currentTimeMillis(); + JAXB2OMElement t1 = new JAXB2OMElement(); + OMElement om = t1.transform(po, tContext); + long duration1 = System.currentTimeMillis() - start; + StringWriter sw = new StringWriter(); + // serializeAndConsume() will trigger the JAXBDataSource.serialize(Writer, OMOutputFormat) + om.serializeAndConsume(sw); + System.out.println(sw.toString()); + + start = System.currentTimeMillis(); + Node node = new JAXB2Node().transform(po, tContext); + XMLStreamReader reader = new Node2XMLStreamReader().transform(node, null); + om = new StAXOMBuilder(reader).getDocumentElement(); + sw = new StringWriter(); + om.serializeAndConsume(sw); + long duration2 = System.currentTimeMillis() - start; + System.out.println(sw.toString()); + System.out.println(duration1 + " vs. " + duration2); + } + + @Test + public void testTransformType() throws Exception { + JAXBElement<PurchaseOrderType> po = createPO(); + DataType<?> sourceDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, XMLType.UNKNOWN); + DataType<?> targetDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, new XMLType(po.getName(), null)); + TransformationContext tContext = new TransformationContextImpl(); + tContext.setSourceDataType(sourceDataType); + tContext.setTargetDataType(targetDataType); + OMElement om = new JAXB2OMElement().transform(po.getValue(), tContext); + StringWriter sw = new StringWriter(); + om.serializeAndConsume(sw); + System.out.println(sw.toString()); + } + + private JAXBElement<PurchaseOrderType> createPO() { + ObjectFactory factory = new ObjectFactory(); + PurchaseOrderType type = factory.createPurchaseOrderType(); + JAXBElement<PurchaseOrderType> po = factory.createPurchaseOrder(type); + type.setItems(factory.createItems()); + type.setComment("123"); + USAddress address = factory.createUSAddress(); + address.setCity("San Jose"); + address.setStreet("ABC St."); + address.setState(USState.CA); + type.setShipTo(address); + return po; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/test/java/org/apache/tuscany/databinding/jaxb/axiom/OMElement2JAXBTestCase.java b/branches/sca-android/modules/databinding-jaxb-axiom/src/test/java/org/apache/tuscany/databinding/jaxb/axiom/OMElement2JAXBTestCase.java new file mode 100644 index 0000000000..3c00307941 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/test/java/org/apache/tuscany/databinding/jaxb/axiom/OMElement2JAXBTestCase.java @@ -0,0 +1,71 @@ +/* + * 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.databinding.jaxb.axiom; + +import java.io.ByteArrayInputStream; + +import javax.xml.namespace.QName; + +import junit.framework.Assert; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.databinding.jaxb.axiom.OMElement2JAXB; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.junit.Test; + +import com.example.ipo.jaxb.PurchaseOrderType; + +/** + * @version $Rev$ $Date$ + */ +public class OMElement2JAXBTestCase { + private static final String XML = + "<ns0:root xmlns:ns0=\"http://ns0\" xmlns:ns2=\"http://www.example.com/IPO\">" + "<ns1:next xmlns:ns1=\"http://ns1\">" + + "<ns2:purchaseOrder>" + + "<shipTo xsi:type=\"ns2:USAddress\" " + + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + + "<street>ABC St.</street><city>San Jose</city><state>CA</state></shipTo>" + + "<ns2:comment>123</ns2:comment><items/>" + + "</ns2:purchaseOrder>" + + "</ns1:next>" + + "</ns0:root>"; + + @Test + public void testTransform() throws Exception { + DataType<?> sourceDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, XMLType.UNKNOWN); + QName qname = new QName("http://www.example.com/IPO", "purchaseOrder"); + DataType<?> targetDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, new XMLType(qname, null)); + TransformationContext tContext = new TransformationContextImpl(); + tContext.setSourceDataType(sourceDataType); + tContext.setTargetDataType(targetDataType); + + StAXOMBuilder builder = new StAXOMBuilder(new ByteArrayInputStream(XML.getBytes("UTF-8"))); + OMElement root = builder.getDocumentElement(); + OMElement next = (OMElement)root.getChildElements().next(); + OMElement po = (OMElement)next.getChildElements().next(); + Object jaxb = new OMElement2JAXB().transform(po, tContext); + Assert.assertTrue(jaxb instanceof PurchaseOrderType); + } +} diff --git a/branches/sca-android/modules/databinding-jaxb-axiom/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-jaxb-axiom/src/test/resources/ipo.xsd new file mode 100644 index 0000000000..241ec15d36 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb-axiom/src/test/resources/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-jaxb/LICENSE b/branches/sca-android/modules/databinding-jaxb/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/branches/sca-android/modules/databinding-jaxb/NOTICE b/branches/sca-android/modules/databinding-jaxb/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-jaxb/pom.xml b/branches/sca-android/modules/databinding-jaxb/pom.xml new file mode 100644 index 0000000000..8b819e06d3 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/pom.xml @@ -0,0 +1,185 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-jaxb</artifactId> + <name>Apache Tuscany SCA Data Binding for JAXB</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <!-- + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + --> + <dependency> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.1</version> + </dependency> + + <dependency> + <groupId>com.sun.xml.bind</groupId> + <artifactId>jaxb-impl</artifactId> + <version>2.1.7</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.jvnet.jaxb.reflection</groupId> + <artifactId>jaxb2-reflection</artifactId> + <version>2.1.4</version> + <scope>test</scope> + </dependency> + </dependencies> + + <repositories> + <repository> + <snapshots> + <enabled>true</enabled> + </snapshots> + <id>java.net</id> + <name>java.net Maven 1.x Repository</name> + <url>http://download.java.net/maven/1</url> + <layout>legacy</layout> + </repository> + </repositories> + + <pluginRepositories> + <pluginRepository> + <id>java.net2</id> + <name>java.net Maven 2.x Repository</name> + <url>http://download.java.net/maven/2</url> + </pluginRepository> + </pluginRepositories> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy</id> + <phase>generate-sources</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.1</version> + <type>jar</type> + </artifactItem> + </artifactItems> + <outputDirectory>${project.build.directory}/endorsed</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine>-Djava.endorsed.dirs=target/endorsed</argLine> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.0</version> + <executions> + <execution> + <id>add-test-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>target/jaxb-source</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.jvnet.jaxb2.maven2</groupId> + <artifactId>maven-jaxb2-plugin</artifactId> + <version>0.5</version> + <executions> + <execution> + <id>generate-jaxb</id> + <phase>generate-test-sources</phase> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + <configuration> + <generatePackage>com.example.ipo.jaxb</generatePackage> + <generateDirectory>${project.build.directory}/jaxb-source</generateDirectory> + <schemaDirectory>${basedir}/src/test/resources</schemaDirectory> + <schemaIncludes> + <include>ipo.xsd</include> + </schemaIncludes> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.jaxb</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.jaxb*</Export-Package> + </instructions> + </configuration> + </plugin> + + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java new file mode 100644 index 0000000000..003b4fb992 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java @@ -0,0 +1,378 @@ +/* + * 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.databinding.jaxb; + +import java.awt.Image; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.activation.DataHandler; +import javax.imageio.ImageIO; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.osoa.sca.ServiceRuntimeException; + +/** + * Provides utilities to convert an object into a different kind of Object. For example, convert a + * String[] into a List<String> + */ +public class DataConverter { + + /** + * This method should return true if the convert method will succeed. + * <p/> + * Note that any changes to isConvertable() must also be accompanied by similar changes to + * convert() + * + * @param obj source object or class + * @param dest destination class + * @return boolean true if convert(..) can convert obj to the destination class + */ + public static boolean isConvertable(Object obj, Class dest) { + Class src = null; + + if (obj != null) { + if (obj instanceof Class) { + src = (Class)obj; + } else { + src = obj.getClass(); + } + } + + if (dest == null) { + return false; + } + + if (src == null) { + return true; + } + + // If we're directly assignable, we're good. + if (dest.isAssignableFrom(src)) { + return true; + } + + // If it's a wrapping conversion, we're good. + if (getWrapperClass(src) == dest) { + return true; + } + if (getWrapperClass(dest) == src) { + return true; + } + + // If it's List -> Array or vice versa, we're good. + if ((Collection.class.isAssignableFrom(src) || src.isArray()) && (Collection.class.isAssignableFrom(dest) || dest + .isArray())) { + + // TODO this should consider the component types instead of returning true. + return true; + } + + // Allow mapping of HashMaps to Hashtables + if (src == HashMap.class && dest == Hashtable.class) + return true; + + // Allow mapping of Calendar to Date + if (Calendar.class.isAssignableFrom(src) && dest == Date.class) { + return true; + } + + if (src.isPrimitive()) { + return isConvertable(getWrapperClass(src), dest); + } + + if (InputStream.class.isAssignableFrom(src) && dest == byte[].class) { + return true; + } + + if (Source.class.isAssignableFrom(src) && dest == byte[].class) { + return true; + } + + if (DataHandler.class.isAssignableFrom(src) && isConvertable(byte[].class, dest)) { + return true; + } + + if (DataHandler.class.isAssignableFrom(src) && dest == Image.class) { + return true; + } + + if (DataHandler.class.isAssignableFrom(src) && dest == Source.class) { + return true; + } + + if (byte[].class.isAssignableFrom(src) && dest == String.class) { + return true; + } + + // If it's a MIME type mapping and we want a DataHandler, + // then we're good. + // REVIEW Do we want to support this + /* + if (dest.getName().equals("javax.activation.DataHandler")) { + String name = src.getName(); + if (src == String.class + || src == java.awt.Image.class + || name.equals("javax.mail.internet.MimeMultipart") + || name.equals("javax.xml.transform.Source")) + return true; + } + */ + + return false; + } + + /** + * Utility function to convert an Object to some desired Class. + * <p/> + * Normally this is used for T[] to List<T> processing. Other conversions are also done (i.e. + * HashMap <->Hashtable, etc.) + * <p/> + * Use the isConvertable() method to determine if conversion is possible. Note that any changes + * to convert() must also be accompanied by similar changes to isConvertable() + * + * @param arg the array to convert + * @param destClass the actual class we want + * @return object of destClass if conversion possible, otherwise returns arg + */ + public static Object convert(Object arg, Class<?> destClass) { + if (destClass == null) { + return arg; + } + + if (arg != null && destClass.isAssignableFrom(arg.getClass())) { + return arg; + } + + // Convert between Calendar and Date + if (arg instanceof Calendar && destClass == Date.class) { + return ((Calendar)arg).getTime(); + } + + // Convert between HashMap and Hashtable + if (arg instanceof HashMap && destClass == Hashtable.class) { + return new Hashtable((HashMap)arg); + } + + if (arg instanceof InputStream && destClass == byte[].class) { + + try { + InputStream is = (InputStream)arg; + return getBytesFromStream(is); + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } + } + + if (arg instanceof Source && destClass == byte[].class) { + try { + if (arg instanceof StreamSource) { + InputStream is = ((StreamSource)arg).getInputStream(); + if (is != null) { + return getBytesFromStream(is); + } + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Result result = new StreamResult(out); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.transform((Source)arg, result); + byte[] bytes = out.toByteArray(); + return bytes; + + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + if (arg instanceof DataHandler) { + try { + InputStream is = ((DataHandler)arg).getInputStream(); + if (destClass == Image.class) { + return ImageIO.read(is); + } else if (destClass == Source.class) { + return new StreamSource(is); + } + byte[] bytes = getBytesFromStream(is); + return convert(bytes, destClass); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + if (arg instanceof byte[] && destClass == String.class) { + return new String((byte[])arg); + } + + // If the destination is an array and the source + // is a suitable component, return an array with + // the single item. + /* REVIEW do we need to support atomic to array conversion ? + if (arg != null && + destClass.isArray() && + !destClass.getComponentType().equals(Object.class) && + destClass.getComponentType().isAssignableFrom(arg.getClass())) { + Object array = + Array.newInstance(destClass.getComponentType(), 1); + Array.set(array, 0, arg); + return array; + } + */ + + // Return if no conversion is available + if (!(arg instanceof Collection || (arg != null && arg.getClass().isArray()))) { + return arg; + } + + if (arg == null) { + return null; + } + + // The arg may be an array or List + Object destValue = null; + int length = 0; + if (arg.getClass().isArray()) { + length = Array.getLength(arg); + } else { + length = ((Collection)arg).size(); + } + + try { + if (destClass.isArray()) { + if (destClass.getComponentType().isPrimitive()) { + + Object array = Array.newInstance(destClass.getComponentType(), length); + // Assign array elements + if (arg.getClass().isArray()) { + for (int i = 0; i < length; i++) { + Array.set(array, i, Array.get(arg, i)); + } + } else { + int idx = 0; + for (Iterator i = ((Collection)arg).iterator(); i.hasNext();) { + Array.set(array, idx++, i.next()); + } + } + destValue = array; + + } else { + Object[] array; + try { + array = (Object[])Array.newInstance(destClass.getComponentType(), length); + } catch (Exception e) { + return arg; + } + + // Use convert to assign array elements. + if (arg.getClass().isArray()) { + for (int i = 0; i < length; i++) { + array[i] = convert(Array.get(arg, i), destClass.getComponentType()); + } + } else { + int idx = 0; + for (Iterator i = ((Collection)arg).iterator(); i.hasNext();) { + array[idx++] = convert(i.next(), destClass.getComponentType()); + } + } + destValue = array; + } + } else if (Collection.class.isAssignableFrom(destClass)) { + Collection newList = null; + try { + // if we are trying to create an interface, build something + // that implements the interface + if (destClass == Collection.class || destClass == List.class) { + newList = new ArrayList(); + } else if (destClass == Set.class) { + newList = new HashSet(); + } else { + newList = (Collection)destClass.newInstance(); + } + } catch (Exception e) { + // No FFDC code needed + // Couldn't build one for some reason... so forget it. + return arg; + } + + if (arg.getClass().isArray()) { + for (int j = 0; j < length; j++) { + newList.add(Array.get(arg, j)); + } + } else { + for (Iterator j = ((Collection)arg).iterator(); j.hasNext();) { + newList.add(j.next()); + } + } + destValue = newList; + } else { + destValue = arg; + } + } catch (Throwable t) { + throw new ServiceRuntimeException(t); + } + + return destValue; + } + + private static byte[] getBytesFromStream(InputStream is) throws IOException { + // TODO This code assumes that available is the length of the stream. + byte[] bytes = new byte[is.available()]; + is.read(bytes); + return bytes; + } + + public static Class getWrapperClass(Class primitive) { + if (primitive == int.class) { + return java.lang.Integer.class; + } else if (primitive == short.class) { + return java.lang.Short.class; + } else if (primitive == boolean.class) { + return java.lang.Boolean.class; + } else if (primitive == byte.class) { + return java.lang.Byte.class; + } else if (primitive == long.class) { + return java.lang.Long.class; + } else if (primitive == double.class) { + return java.lang.Double.class; + } else if (primitive == float.class) { + return java.lang.Float.class; + } else if (primitive == char.class) { + return java.lang.Character.class; + } + + return null; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DefaultXMLAdapterExtensionPoint.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DefaultXMLAdapterExtensionPoint.java new file mode 100644 index 0000000000..062da48206 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DefaultXMLAdapterExtensionPoint.java @@ -0,0 +1,60 @@ +/* + * 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.databinding.jaxb; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +/** + * @version $Rev$ $Date$ + */ +public class DefaultXMLAdapterExtensionPoint implements XMLAdapterExtensionPoint { + private Map<Class<?>, Class<? extends XmlAdapter>> adapters = + new ConcurrentHashMap<Class<?>, Class<? extends XmlAdapter>>(); + + public void addAdapter(Class<?> boundType, Class<? extends XmlAdapter> adapter) { + adapters.put(boundType, adapter); + } + + public Class<? extends XmlAdapter> getAdapter(Class<?> boundType) { + Class<? extends XmlAdapter> cls = adapters.get(boundType); + if (cls != null) { + return cls; + } + for (Map.Entry<Class<?>, Class<? extends XmlAdapter>> e : adapters.entrySet()) { + if (e.getKey().isAssignableFrom(boundType)) { + return e.getValue(); + } + } + return null; + } + + @SuppressWarnings("unchecked") + public Class<? extends XmlAdapter> removeAdapter(Class<?> boundType) { + return adapters.remove(boundType); + } + + public Map<Class<?>, Class<? extends XmlAdapter>> getAdapters() { + return adapters; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2Node.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2Node.java new file mode 100644 index 0000000000..3e262c7d12 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2Node.java @@ -0,0 +1,75 @@ +/* + * 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.databinding.jaxb; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * + * @version $Rev$ $Date$ + */ +public class JAXB2Node extends BaseTransformer<Object, Node> implements PullTransformer<Object, Node> { + + public Node transform(Object source, TransformationContext tContext) { +// if (source == null) { +// return null; +// } + try { + JAXBContext context = JAXBContextHelper.createJAXBContext(tContext, true); + Marshaller marshaller = context.createMarshaller(); + // FIXME: The default Marshaller doesn't support + // marshaller.getNode() + Document document = DOMHelper.newDocument(); + Object jaxbElement = JAXBContextHelper.createJAXBElement(context, tContext.getSourceDataType(), source); + marshaller.marshal(jaxbElement, document); + return DOMHelper.adjustElementName(tContext, document.getDocumentElement()); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 30; + } + + @Override + public String getSourceDataBinding() { + return JAXBDataBinding.NAME; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2SAX.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2SAX.java new file mode 100644 index 0000000000..eee5c77285 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2SAX.java @@ -0,0 +1,70 @@ +/* + * 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.databinding.jaxb; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; + +/** + * @version $Rev$ $Date$ + */ +public class JAXB2SAX extends BaseTransformer<Object, ContentHandler> implements + PushTransformer<Object, ContentHandler> { + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, java.lang.Object, org.apache.tuscany.sca.databinding.TransformationContext) + */ + public void transform(Object source, ContentHandler target, TransformationContext tContext) { + try { + JAXBContext context = JAXBContextHelper.createJAXBContext(tContext, true); + Marshaller marshaller = context.createMarshaller(); + Object jaxbElement = JAXBContextHelper.createJAXBElement(context, tContext.getSourceDataType(), source); + marshaller.marshal(jaxbElement, target); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 20; + } + + @Override + public String getSourceDataBinding() { + return JAXBDataBinding.NAME; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2String.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2String.java new file mode 100644 index 0000000000..29951a5e16 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2String.java @@ -0,0 +1,77 @@ +/* + * 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.databinding.jaxb; + +import java.io.StringWriter; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.xml.XMLStringDataBinding; + +/** + * + * @version $Rev$ $Date$ + */ +public class JAXB2String extends BaseTransformer<Object, String> implements PullTransformer<Object, String> { + + public String transform(Object source, TransformationContext tContext) { + try { + JAXBContext context = JAXBContextHelper.createJAXBContext(tContext, true); + Marshaller marshaller = context.createMarshaller(); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + Object jaxbElement = JAXBContextHelper.createJAXBElement(context, tContext.getSourceDataType(), source); + marshaller.marshal(jaxbElement, result); + return writer.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 30; + } + + @Override + public String getSourceDataBinding() { + return JAXBDataBinding.NAME; + } + + @Override + public String getTargetDataBinding() { + return XMLStringDataBinding.NAME; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java new file mode 100644 index 0000000000..296c39c50f --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java @@ -0,0 +1,293 @@ +/* + * 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.databinding.jaxb; + +import java.awt.Image; +import java.net.URI; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import javax.activation.DataHandler; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.transform.Source; + +import org.apache.tuscany.sca.databinding.util.LRUCache; + +/** + * @version $Rev$ $Date$ + */ +public class JAXBContextCache { + private static final int CACHE_SIZE = 128; + + private static HashMap<String, Class<?>> loadClassMap = new HashMap<String, Class<?>>(); + + static { + loadClassMap.put("byte", byte.class); + loadClassMap.put("int", int.class); + loadClassMap.put("short", short.class); + loadClassMap.put("long", long.class); + loadClassMap.put("float", float.class); + loadClassMap.put("double", double.class); + loadClassMap.put("boolean", boolean.class); + loadClassMap.put("char", char.class); + loadClassMap.put("void", void.class); + } + + protected static Class<?>[] JAXB_BUILTIN_CLASSES = + {byte[].class, boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, + short.class, void.class, java.awt.Image.class, java.io.File.class, java.lang.Boolean.class, + java.lang.Byte.class, java.lang.Character.class, java.lang.Class.class, java.lang.Double.class, + java.lang.Float.class, java.lang.Integer.class, java.lang.Long.class, java.lang.Object.class, + java.lang.Short.class, java.lang.String.class, java.lang.Void.class, java.math.BigDecimal.class, + java.math.BigInteger.class, java.net.URI.class, java.net.URL.class, java.util.Calendar.class, + java.util.Date.class, java.util.GregorianCalendar.class, java.util.UUID.class, + javax.activation.DataHandler.class, javax.xml.bind.JAXBElement.class, javax.xml.datatype.Duration.class, + javax.xml.datatype.XMLGregorianCalendar.class, javax.xml.namespace.QName.class, + javax.xml.transform.Source.class}; + + protected static final Set<Class<?>> BUILTIN_CLASSES_SET = new HashSet<Class<?>>(Arrays.asList(JAXB_BUILTIN_CLASSES)); + + /* + protected static Class<?>[] COMMON_ARRAY_CLASSES = + new Class[] {char[].class, short[].class, int[].class, long[].class, float[].class, double[].class, + String[].class + }; + + protected static final Set<Class<?>> COMMON_CLASSES_SET = new HashSet<Class<?>>(Arrays.asList(COMMON_ARRAY_CLASSES)); + */ + + protected LRUCache<Object, JAXBContext> cache; + protected LRUCache<JAXBContext, Unmarshaller> upool; + protected LRUCache<JAXBContext, Marshaller> mpool; + + // protected JAXBContext commonContext; + protected JAXBContext defaultContext; + + public JAXBContextCache() { + this(CACHE_SIZE, CACHE_SIZE, CACHE_SIZE); + } + + public JAXBContextCache(int contextSize, int marshallerSize, int unmarshallerSize) { + cache = new LRUCache<Object, JAXBContext>(contextSize); + upool = new LRUCache<JAXBContext, Unmarshaller>(unmarshallerSize); + mpool = new LRUCache<JAXBContext, Marshaller>(marshallerSize); + defaultContext = getDefaultJAXBContext(); + } + + public static JAXBContext getDefaultJAXBContext() { + try { + return JAXBContext.newInstance(); + } catch (JAXBException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * @param name of primitive type + * @return primitive Class or null + */ + public static Class<?> getPrimitiveClass(String text) { + return loadClassMap.get(text); + } + + /** + * Return the class for this name + * + * @return Class + */ + private static Class<?> forName(final String className, final boolean initialize, final ClassLoader classloader) + throws ClassNotFoundException { + // NOTE: This method must remain private because it uses AccessController + Class<?> cl = null; + try { + cl = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() { + public Class<?> run() throws ClassNotFoundException { + // Class.forName does not support primitives + Class<?> cls = getPrimitiveClass(className); + if (cls == null) { + cls = Class.forName(className, initialize, classloader); + } + return cls; + } + }); + } catch (PrivilegedActionException e) { + throw (ClassNotFoundException)e.getException(); + } + + return cl; + } + + /** + * @param p Package + * @param cl + * @return true if each package has a ObjectFactory class or package-info + */ + public static boolean checkPackage(String p, ClassLoader cl) { + + // Each package must have an ObjectFactory + try { + Class<?> cls = forName(p + ".ObjectFactory", false, cl); + if (cls != null) { + return true; + } + //Catch Throwable as ClassLoader can throw an NoClassDefFoundError that + //does not extend Exception. So we will absorb any Throwable exception here. + } catch (Throwable e) { + // Ignore + } + + try { + Class<?> cls = forName(p + ".package-info", false, cl); + if (cls != null) { + return cls.isAnnotationPresent(XmlSchema.class); + } + //Catch Throwable as ClassLoader can throw an NoClassDefFoundError that + //does not extend Exception. So we will absorb any Throwable exception here. + } catch (Throwable e) { + // Ignore + } + + return false; + } + + public Marshaller getMarshaller(JAXBContext context) throws JAXBException { + synchronized (mpool) { + Marshaller marshaller = mpool.get(context); + if (marshaller == null) { + marshaller = context.createMarshaller(); + mpool.put(context, marshaller); + } + return marshaller; + } + } + + public Unmarshaller getUnmarshaller(JAXBContext context) throws JAXBException { + synchronized (upool) { + Unmarshaller unmarshaller = upool.get(context); + if (unmarshaller == null) { + unmarshaller = context.createUnmarshaller(); + upool.put(context, unmarshaller); + } + return unmarshaller; + } + } + + public LRUCache<Object, JAXBContext> getCache() { + return cache; + } + + public JAXBContext getJAXBContext(Class<?> cls) throws JAXBException { + if (BUILTIN_CLASSES_SET.contains(cls)) { + return defaultContext; + } + synchronized (cache) { + JAXBContext context = cache.get(cls); + if (context != null) { + return context; + } + Package pkg = cls.getPackage(); + if (pkg != null) { + context = cache.get(pkg); + if (context != null) { + return context; + } + } + + if (pkg != null && checkPackage(pkg.getName(), cls.getClassLoader())) { + context = JAXBContext.newInstance(pkg.getName(), cls.getClassLoader()); + cache.put(pkg, context); + } else { + context = JAXBContext.newInstance(cls); + cache.put(cls, context); + } + return context; + + } + } + + public JAXBContext getJAXBContext(Class<?>[] classes) throws JAXBException { + Set<Class<?>> classSet = new HashSet<Class<?>>(Arrays.asList(classes)); + return getJAXBContext(classSet); + } + + public JAXBContext getJAXBContext(Set<Class<?>> classes) throws JAXBException { + // Remove the JAXB built-in types to maximize the cache hit + Set<Class<?>> classSet = new HashSet<Class<?>>(classes); + classSet.removeAll(BUILTIN_CLASSES_SET); + + // FIXME: [rfeng] Remove java classes that are mapped to the same XSD type to avoid + // conflicts + if (classSet.contains(Date[].class)) { + classSet.remove(Calendar[].class); + } + + if (classSet.contains(URI[].class)) { + classSet.remove(UUID[].class); + } + + if (classSet.contains(Source[].class)) { + classSet.remove(Image[].class); + classSet.remove(DataHandler[].class); + } + + if(classSet.isEmpty()) { + return defaultContext; + } + + // For single class + if (classSet.size() == 1) { + return getJAXBContext(classSet.iterator().next()); + } + synchronized (cache) { + JAXBContext context = cache.get(classSet); + if (context != null) { + return context; + } + context = JAXBContext.newInstance(classSet.toArray(new Class<?>[classSet.size()])); + cache.put(classSet, context); + return context; + } + } + + public void clear() { + synchronized (cache) { + cache.clear(); + } + synchronized (upool) { + upool.clear(); + } + synchronized (upool) { + upool.clear(); + } + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java new file mode 100644 index 0000000000..6d66f10a8e --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java @@ -0,0 +1,429 @@ +/* + * 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.databinding.jaxb; + +import java.beans.Introspector; +import java.io.IOException; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.JAXBIntrospector; +import javax.xml.bind.Marshaller; +import javax.xml.bind.SchemaOutputResolver; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.XmlType; +import javax.xml.namespace.QName; +import javax.xml.transform.Result; +import javax.xml.transform.dom.DOMResult; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.util.LRUCache; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Node; + +/** + * + * @version $Rev$ $Date$ + */ +// FIXME: [rfeng] We probably should turn this into a pluggable system service +public class JAXBContextHelper { + // public static final String JAXB_CLASSES = "jaxb.classes"; + + // public static final String JAXB_CONTEXT_PATH = "jaxb.contextPath"; + + private static final JAXBContextCache cache = new JAXBContextCache(); + + private JAXBContextHelper() { + } + + /** + * Create a JAXBContext for a given class + * @param cls + * @return + * @throws JAXBException + */ + public static JAXBContext createJAXBContext(Class<?> cls) throws JAXBException { + return cache.getJAXBContext(cls); + } + + public static JAXBContext createJAXBContext(TransformationContext tContext, boolean source) throws JAXBException { + if (tContext == null) + throw new TransformationException("JAXB context is not set for the transformation."); + + // TODO: [rfeng] Need to figure out what's the best grantularity to create the JAXBContext + // per interface, operation or parameter + Operation op = source ? tContext.getSourceOperation() : tContext.getTargetOperation(); + if (op != null) { + synchronized (op) { + JAXBContext context = op.getInputType().getMetaData(JAXBContext.class); + if (context == null) { + context = createJAXBContext(getDataTypes(op, true)); + op.getInputType().setMetaData(JAXBContext.class, context); + } + return context; + } + } + + // For property transformation, the operation can be null + DataType<?> dataType = source ? tContext.getSourceDataType() : tContext.getTargetDataType(); + return createJAXBContext(dataType); + + } + + public static JAXBContext createJAXBContext(DataType dataType) throws JAXBException { + return createJAXBContext(findClasses(dataType)); + } + + public static Unmarshaller getUnmarshaller(JAXBContext context) throws JAXBException { + return cache.getUnmarshaller(context); + } + + public static Marshaller getMarshaller(JAXBContext context) throws JAXBException { + return cache.getMarshaller(context); + } + + @SuppressWarnings("unchecked") + public static Object createJAXBElement(JAXBContext context, DataType dataType, Object value) { + Class<?> type = dataType == null ? value.getClass() : dataType.getPhysical(); + QName name = JAXBDataBinding.ROOT_ELEMENT; + if (context != null) { + Object logical = dataType == null ? null : dataType.getLogical(); + if (logical instanceof XMLType) { + XMLType xmlType = (XMLType)logical; + if (xmlType.isElement()) { + name = xmlType.getElementName(); + } else { + /** + * Set the declared type to Object.class so that xsi:type + * will be produced + */ + type = Object.class; + } + } else { + type = Object.class; + } + } + + JAXBIntrospector introspector = context.createJAXBIntrospector(); + Object element = null; + if (value != null && introspector.isElement(value)) { + // NOTE: [rfeng] We cannot wrap an element in a JAXBElement + element = value; + } + if (element == null) { + element = new JAXBElement(name, type, value); + } + return element; + } + + @SuppressWarnings("unchecked") + public static Object createReturnValue(JAXBContext context, DataType dataType, Object value) { + Class<?> cls = getJavaType(dataType); + if (cls == JAXBElement.class) { + return createJAXBElement(context, dataType, value); + } else { + if (value instanceof JAXBElement) { + return ((JAXBElement)value).getValue(); + } else { + return value; + } + } + } + + /** + * Create a JAXContext for an array of classes + * @param classes + * @return + * @throws JAXBException + */ + public static JAXBContext createJAXBContext(Class<?>[] classes) throws JAXBException { + return cache.getJAXBContext(classes); + } + + public static JAXBContext createJAXBContext(Set<Class<?>> classes) throws JAXBException { + return cache.getJAXBContext(classes); + } + + /** + * Create a JAXBContext for a given java interface + * @param intf + * @return + * @throws JAXBException + */ + public static JAXBContext createJAXBContext(Interface intf, boolean useWrapper) throws JAXBException { + synchronized (cache) { + LRUCache<Object, JAXBContext> map = cache.getCache(); + Integer key = new Integer(System.identityHashCode(intf)); + JAXBContext context = map.get(key); + if (context != null) { + return context; + } + List<DataType> dataTypes = getDataTypes(intf, useWrapper); + context = createJAXBContext(dataTypes); + map.put(key, context); + return context; + } + } + + public static JAXBContext createJAXBContext(List<DataType> dataTypes) throws JAXBException { + JAXBContext context; + Set<Class<?>> classes = new HashSet<Class<?>>(); + Set<Type> visited = new HashSet<Type>(); + for (DataType d : dataTypes) { + findClasses(d, classes, visited); + } + + context = createJAXBContext(classes); + return context; + } + + private static Set<Class<?>> findClasses(DataType d) { + Set<Class<?>> classes = new HashSet<Class<?>>(); + Set<Type> visited = new HashSet<Type>(); + findClasses(d, classes, visited); + return classes; + } + + private static void findClasses(DataType d, Set<Class<?>> classes, Set<Type> visited) { + if (d == null) { + return; + } + String db = d.getDataBinding(); + if (JAXBDataBinding.NAME.equals(db) || (db != null && db.startsWith("java:")) || db == null) { + if (!d.getPhysical().isInterface() && !JAXBElement.class.isAssignableFrom(d.getPhysical())) { + classes.add(d.getPhysical()); + } + } + if (d.getPhysical() != d.getGenericType()) { + findClasses(d.getGenericType(), classes, visited); + } + } + + /** + * Find referenced classes in the generic type + * @param type + * @param classSet + * @param visited + */ + private static void findClasses(Type type, Set<Class<?>> classSet, Set<Type> visited) { + if (visited.contains(type) || type == null) { + return; + } + visited.add(type); + if (type instanceof Class) { + Class<?> cls = (Class<?>)type; + if (!cls.isInterface()) { + classSet.add(cls); + } + return; + } else if (type instanceof ParameterizedType) { + ParameterizedType pType = (ParameterizedType)type; + findClasses(pType.getRawType(), classSet, visited); + for (Type t : pType.getActualTypeArguments()) { + findClasses(t, classSet, visited); + } + } else if (type instanceof TypeVariable) { + TypeVariable<?> tv = (TypeVariable<?>)type; + for (Type t : tv.getBounds()) { + findClasses(t, classSet, visited); + } + } else if (type instanceof GenericArrayType) { + GenericArrayType gType = (GenericArrayType)type; + findClasses(gType, classSet, visited); + } else if (type instanceof WildcardType) { + WildcardType wType = (WildcardType)type; + for (Type t : wType.getLowerBounds()) { + findClasses(t, classSet, visited); + } + for (Type t : wType.getUpperBounds()) { + findClasses(t, classSet, visited); + } + } + } + + public static JAXBContext createJAXBContext(Interface intf) throws JAXBException { + return createJAXBContext(intf, true); + } + + /** + * @param intf + * @param useWrapper Use wrapper classes? + * @return + */ + private static List<DataType> getDataTypes(Interface intf, boolean useWrapper) { + List<DataType> dataTypes = new ArrayList<DataType>(); + for (Operation op : intf.getOperations()) { + getDataTypes(dataTypes, op, useWrapper); + } + return dataTypes; + } + + private static List<DataType> getDataTypes(Operation op, boolean useWrapper) { + List<DataType> dataTypes = new ArrayList<DataType>(); + getDataTypes(dataTypes, op, useWrapper); + return dataTypes; + } + + private static void getDataTypes(List<DataType> dataTypes, Operation op, boolean useWrapper) { + WrapperInfo wrapper = op.getWrapper(); + if (useWrapper && wrapper != null) { + DataType dt1 = wrapper.getInputWrapperType(); + if (dt1 != null) { + dataTypes.add(dt1); + } + DataType dt2 = wrapper.getOutputWrapperType(); + if (dt2 != null) { + dataTypes.add(dt2); + } + } + // FIXME: [rfeng] We may need to find the referenced classes in the child types + // else + { + for (DataType dt1 : op.getInputType().getLogical()) { + dataTypes.add(dt1); + } + DataType dt2 = op.getOutputType(); + if (dt2 != null) { + dataTypes.add(dt2); + } + } + for (DataType<DataType> dt3 : op.getFaultTypes()) { + DataType dt4 = dt3.getLogical(); + if (dt4 != null) { + dataTypes.add(dt4); + } + } + } + + public static Class<?> getJavaType(DataType<?> dataType) { + if (dataType == null) { + return null; + } + Class type = dataType.getPhysical(); + if (JAXBElement.class.isAssignableFrom(type)) { + Type generic = dataType.getGenericType(); + type = Object.class; + } + if (type == Object.class && dataType.getLogical() instanceof XMLType) { + XMLType xType = (XMLType)dataType.getLogical(); + Class javaType = SimpleTypeMapperImpl.getJavaType(xType.getTypeName()); + if (javaType != null) { + type = javaType; + } + } + return type; + } + + public static XMLType getXmlTypeName(Class<?> javaType) { + if (javaType.isInterface()) { + // JAXB doesn't support interfaces + return null; + } + String namespace = null; + String name = null; + Package pkg = javaType.getPackage(); + if (pkg != null) { + XmlSchema schema = pkg.getAnnotation(XmlSchema.class); + if (schema != null) { + namespace = schema.namespace(); + } + } + + QName elementQName = null; + QName typeQName = null; + XmlRootElement rootElement = javaType.getAnnotation(XmlRootElement.class); + if (rootElement != null) { + String elementName = rootElement.name(); + String elementNamespace = rootElement.namespace(); + if (elementNamespace.equals("##default")) { + elementNamespace = namespace; + } + if (elementName.equals("##default")) { + elementName = Introspector.decapitalize(javaType.getSimpleName()); + } + elementQName = new QName(elementNamespace, elementName); + } + XmlType type = javaType.getAnnotation(XmlType.class); + if (type != null) { + String typeNamespace = type.namespace(); + String typeName = type.name(); + + if (typeNamespace.equals("##default")) { + // namespace is from the package + typeNamespace = namespace; + } + + if (typeName.equals("##default")) { + typeName = Introspector.decapitalize(javaType.getSimpleName()); + } + typeQName = new QName(typeNamespace, typeName); + } else { + XmlEnum xmlEnum = javaType.getAnnotation(XmlEnum.class); + if (xmlEnum != null) { + name = Introspector.decapitalize(javaType.getSimpleName()); + typeQName = new QName(namespace, name); + } + } + if (elementQName == null && typeQName == null) { + return null; + } + return new XMLType(elementQName, typeQName); + } + + public static Node generateSchema(JAXBContext context) throws Exception { + SchemaOutputResolverImpl resolver = new SchemaOutputResolverImpl(); + context.generateSchema(resolver); + return resolver.getSchema(); + } + + public static class SchemaOutputResolverImpl extends SchemaOutputResolver { + private DOMResult result = new DOMResult(); + + @Override + public Result createOutput(String ns, String file) throws IOException { + result.setSystemId("sca:dom"); + return result; + } + + public Node getSchema() { + return result != null ? result.getNode() : null; + } + + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java new file mode 100644 index 0000000000..eebb4b2e37 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java @@ -0,0 +1,132 @@ +/* + * 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.databinding.jaxb; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Document; + +/** + * JAXB DataBinding + * + * @version $Rev$ $Date$ + */ +public class JAXBDataBinding extends BaseDataBinding { + public static final String NAME = JAXBElement.class.getName(); + public static final String[] ALIASES = new String[] {"jaxb"}; + + public static final String ROOT_NAMESPACE = "http://tuscany.apache.org/xmlns/sca/databinding/jaxb/1.0"; + public static final QName ROOT_ELEMENT = new QName(ROOT_NAMESPACE, "root"); + + private JAXBWrapperHandler wrapperHandler; + private JAXBTypeHelper xmlTypeHelper; + + public JAXBDataBinding() { + super(NAME, ALIASES, JAXBElement.class); + this.wrapperHandler = new JAXBWrapperHandler(); + this.xmlTypeHelper = new JAXBTypeHelper(); + } + + @Override + public boolean introspect(DataType dataType, Operation operation) { + Class javaType = dataType.getPhysical(); + if (JAXBElement.class.isAssignableFrom(javaType)) { + Type type = javaType.getGenericSuperclass(); + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = ((ParameterizedType)type); + Type rawType = parameterizedType.getRawType(); + if (rawType == JAXBElement.class) { + Type actualType = parameterizedType.getActualTypeArguments()[0]; + if (actualType instanceof Class) { + XMLType xmlType = JAXBContextHelper.getXmlTypeName((Class)actualType); + dataType.setLogical(xmlType); + dataType.setDataBinding(NAME); + return true; + } + } + } + if (dataType.getLogical() == null) { + dataType.setLogical(XMLType.UNKNOWN); + } + dataType.setDataBinding(NAME); + return true; + } + + XMLType xmlType = JAXBContextHelper.getXmlTypeName(javaType); + if (xmlType == null) { + return false; + } + dataType.setLogical(xmlType); + dataType.setDataBinding(NAME); + return true; + } + + @SuppressWarnings("unchecked") + @Override + public Object copy(Object arg, DataType dataType, Operation operation) { + try { + boolean isElement = false; + if (dataType == null) { + Class cls = arg.getClass(); + if (arg instanceof JAXBElement) { + isElement = true; + cls = ((JAXBElement)arg).getDeclaredType(); + } + dataType = new DataTypeImpl<XMLType>(NAME, cls, XMLType.UNKNOWN); + } + JAXBContext context = JAXBContextHelper.createJAXBContext(dataType); + arg = JAXBContextHelper.createJAXBElement(context, dataType, arg); + Document doc = DOMHelper.newDocument(); + context.createMarshaller().marshal(arg, doc); + Object value = context.createUnmarshaller().unmarshal(doc, dataType.getPhysical()); + if (isElement && value instanceof JAXBElement) { + return value; + } + return JAXBContextHelper.createReturnValue(context, dataType, value); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public WrapperHandler getWrapperHandler() { + return wrapperHandler; + } + + @Override + public XMLTypeHelper getXMLTypeHelper() { + // return new JAXBTypeHelper(); + return xmlTypeHelper; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBPropertyDescriptor.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBPropertyDescriptor.java new file mode 100644 index 0000000000..8805d72627 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBPropertyDescriptor.java @@ -0,0 +1,302 @@ +/* + * 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.databinding.jaxb; + +import java.beans.IndexedPropertyDescriptor; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; + +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +import org.osoa.sca.ServiceRuntimeException; + +/** + * A PropertyDescriptor provides acesss to a bean property. Values can be queried/changed using the + * read and writer methods of the PropertyDescriptor. + * <p/> + * A PropertyDescriptorPlus object wraps a PropertyDescriptor and supplies enhanced set/get methods + * that match JAXB semantis. + * <p/> + * For example, the set(..) method is smart enough to add lists, arrays and atomic values on JAXB + * beans. + * <p/> + * The PropertyDescriptorPlus object also stores the xmlName of the property. + * + * @See XMLRootElementUtil.createPropertyDescriptorMap , which creates the PropertyDescriptorPlus + * objects + */ +public class JAXBPropertyDescriptor implements Comparable<JAXBPropertyDescriptor> { + PropertyDescriptor descriptor; + QName xmlName = null; + int index; + + /** + * Package protected constructor. Only created by XMLRootElementUtil.createPropertyDescriptorMap + * @param descriptor + * @param index TODO + * @param propertyName + * + * @see XMLRootElementUtil.createPropertyDescriptorMap + */ + JAXBPropertyDescriptor(PropertyDescriptor descriptor, QName xmlName, int index) { + super(); + this.descriptor = descriptor; + this.xmlName = xmlName; + } + + /** + * Package protected constructor. Only created by XMLRootElementUtil.createPropertyDescriptorMap + * @param descriptor + * @param index TODO + * @param propertyName + * + * @see XMLRootElementUtil.createPropertyDescriptorMap + */ + JAXBPropertyDescriptor(PropertyDescriptor descriptor, String xmlName, int index) { + super(); + this.descriptor = descriptor; + this.xmlName = new QName("", xmlName); + } + + public int compareTo(JAXBPropertyDescriptor o) { + return index - o.index; + } + + /** @return xmlname */ + public String getXmlName() { + return xmlName.getLocalPart(); + } + + public QName getXmlQName() { + return xmlName; + } + + /** @return property type */ + public Class<?> getPropertyType() { + return descriptor.getPropertyType(); + } + + /** @return property name */ + public String getPropertyName() { + return descriptor.getName(); + } + + /** + * Get the object + * + * @param targetBean + * @return Object for this property or null + * @throws InvocationTargetException + * @throws IllegalAccessException + */ + public Object get(Object targetBean) throws InvocationTargetException, IllegalAccessException { + Method method = descriptor.getReadMethod(); + if (method == null && descriptor.getPropertyType() == Boolean.class) { + String propertyName = descriptor.getName(); + if (propertyName != null) { + String methodName = "is"; + methodName = + methodName + ((propertyName.length() > 0) ? propertyName.substring(0, 1).toUpperCase() : ""); + methodName = methodName + ((propertyName.length() > 1) ? propertyName.substring(1) : ""); + try { + method = targetBean.getClass().getMethod(methodName); + } catch (NoSuchMethodException e) { + } + } + } + if (method == null) { + throw new ServiceRuntimeException("No getter is found"); + } + Object ret = method.invoke(targetBean); + if (method.getReturnType() == JAXBElement.class) { + ret = ((JAXBElement<?>)ret).getValue(); + } + return ret; + } + + /** + * Set the object + * + * @param targetBean + * @param propValue + * @throws InvocationTargetException + * @throws IllegalAccessException + * @throws JAXBWrapperException + */ + public void set(Object targetBean, Object propValue) throws InvocationTargetException, IllegalAccessException, + JAXBWrapperException { + + Method writeMethod = null; + try { + // No set occurs if the value is null + if (propValue == null) { + return; + } + + // There are 3 different types of setters that can occur. + // 1) Normal Attomic Setter : setFoo(type) + // 2) Indexed Array Setter : setFoo(type[]) + // 3) No Setter case if the property is a List<T>. + + writeMethod = descriptor.getWriteMethod(); + if (descriptor instanceof IndexedPropertyDescriptor) { + // Set for indexed T[] + setIndexedArray(targetBean, propValue, writeMethod); + } else if (writeMethod == null) { + // Set for List<T> + setList(targetBean, propValue); + } else if (descriptor.getPropertyType() == JAXBElement.class) { + if (propValue != null) { + Class<?> clazz = propValue.getClass(); + JAXBElement<?> element = new JAXBElement(xmlName, clazz, propValue); + setAtomic(targetBean, element, writeMethod); + } + } else { + // Normal case + setAtomic(targetBean, propValue, writeMethod); + } + } catch (RuntimeException e) { + throw e; + } + } + + /** + * Set the property value onto targetBean using the writeMethod + * + * @param targetBean + * @param propValue + * @param writeMethod (set(T)) + * @throws InvocationTargetException + * @throws IllegalAccessException + * @throws JAXBWrapperException + */ + private void setAtomic(Object targetBean, Object propValue, Method writeMethod) throws InvocationTargetException, + IllegalAccessException, JAXBWrapperException { + // JAXB provides setters for atomic value. + + if (propValue != null) { + // Normal case + Object[] SINGLE_PARAM = new Object[1]; + SINGLE_PARAM[0] = propValue; + writeMethod.invoke(targetBean, SINGLE_PARAM); + } else { + Class<?>[] paramTypes = writeMethod.getParameterTypes(); + + if (paramTypes != null && paramTypes.length == 1) { + Class<?> paramType = paramTypes[0]; + if (paramType.isPrimitive() && propValue == null) { + //Ignoring null value for primitive type, this could potentially be the way of a customer indicating to set + //default values defined in JAXBObject/xmlSchema. + return; + } + } + } + + } + + /** + * Set the property value using the indexed array setter + * + * @param targetBean + * @param propValue + * @param writeMethod set(T[]) + * @throws InvocationTargetException + * @throws IllegalAccessException + * @throws JAXBWrapperException + */ + private void setIndexedArray(Object targetBean, Object propValue, Method writeMethod) + throws InvocationTargetException, IllegalAccessException, JAXBWrapperException { + + Class<?> paramType = writeMethod.getParameterTypes()[0]; + Object value = asArray(propValue, paramType); + // JAXB provides setters for atomic value. + Object[] SINGLE_PARAM = new Object[1]; + SINGLE_PARAM[0] = value; + + writeMethod.invoke(targetBean, SINGLE_PARAM); + } + + /** + * Set the property value for the collection case. + * + * @param targetBean + * @param propValue + * @throws InvocationTargetException + * @throws IllegalAccessException + * @throws JAXBWrapperException + */ + private void setList(Object targetBean, Object propValue) throws InvocationTargetException, IllegalAccessException, + JAXBWrapperException { + // For the List<T> case, there is no setter. + // You are supposed to use the getter to obtain access to the collection and then add the collection + + Collection value = asCollection(propValue, descriptor.getPropertyType()); + Collection collection = (Collection)get(targetBean); + + // Now add our our object to the collection + collection.clear(); + if (propValue != null) { + collection.addAll(value); + } + } + + /** + * @param propValue + * @param destType + * @return propValue as a Collection + */ + private static Collection asCollection(Object propValue, Class<?> destType) { + // TODO Missing function + // Convert the object into an equivalent object that is a collection + if (DataConverter.isConvertable(propValue, destType)) { + return (Collection)DataConverter.convert(propValue, destType); + } else { + String objectClass = (propValue == null) ? "null" : propValue.getClass().getName(); + throw new ServiceRuntimeException("Cannot convert " + objectClass); + } + } + + /** + * @param propValue + * @param destType T[] + * @return array of component type + */ + private static Object asArray(Object propValue, Class<?> destType) { + if (DataConverter.isConvertable(propValue, destType)) { + return DataConverter.convert(propValue, destType); + } else { + String objectClass = (propValue == null) ? "null" : propValue.getClass().getName(); + throw new ServiceRuntimeException("Cannot convert " + objectClass); + + } + } + + @Override + public String toString() { + String value = "PropertyDescriptorPlus["; + value += " name=" + this.getPropertyName(); + value += " type=" + this.getPropertyType().getName(); + value += " propertyDecriptor=" + this.descriptor; + return value + "]"; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTypeHelper.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTypeHelper.java new file mode 100644 index 0000000000..573e636884 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTypeHelper.java @@ -0,0 +1,276 @@ +/* + * 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.databinding.jaxb; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.SchemaOutputResolver; +import javax.xml.namespace.QName; +import javax.xml.transform.Result; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.xsd.XSDFactory; +import org.apache.tuscany.sca.xsd.XSDefinition; +import org.apache.ws.commons.schema.resolver.URIResolver; +import org.osoa.sca.ServiceRuntimeException; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +public class JAXBTypeHelper implements XMLTypeHelper { + private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; + private static final String ANYTYPE_NAME = "anyType"; + private static final QName ANYTYPE_QNAME = new QName(SCHEMA_NS, ANYTYPE_NAME); + + // private List<Class<?>> types = new ArrayList<Class<?>>(); + + public JAXBTypeHelper() { + super(); + } + + public TypeInfo getTypeInfo(Class javaType, Object logical) { + QName xmlType = JavaXMLMapper.getXMLType(javaType); + if (xmlType != null) { + return new TypeInfo(xmlType, true, null); + } else if (javaType.isInterface()) { + return new TypeInfo(ANYTYPE_QNAME, true, null); + } else { + // types.add(javaType); + if (logical instanceof XMLType) { + xmlType = ((XMLType)logical).getTypeName(); + } + if (xmlType == null) { + xmlType = new QName(jaxbRIDecapitalize(javaType.getSimpleName())); + } + return new TypeInfo(xmlType, false, null); + } + } + + /** + * The JAXB RI doesn't implement the decapitalization algorithm in the + * JAXB spec. See Sun bug 6505643 for details. This means that we need + * to mimic the incorrect algorithm for references from wrapper schemas. + */ + private String jaxbRIDecapitalize(String name) { + // find first lower case char in name + int lower = name.length(); + for (int i = 0; i < name.length(); i++) { + if (Character.isLowerCase(name.charAt(i))) { + lower = i; + break; + } + } + + int decap; + if (name.length() == 0) { + decap = 0; // empty string: nothing to do + } else if (lower == 0) { + decap = 0; // first char is lower case: nothing to do + } else if (lower == 1) { + decap = 1; // one upper followed by lower: decapitalize 1 char + } else if (lower < name.length()) { + decap = lower - 1; // n uppers followed by at least one lower: decapitalize n-1 chars + } else { + decap = name.length(); // all upper case: decapitalize all chars + } + + return name.substring(0, decap).toLowerCase() + name.substring(decap); + } + + /* + public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver) { + List<XSDefinition> definitions = new ArrayList<XSDefinition>(); + generateJAXBSchemas(definitions, factory); + return definitions; + } + */ + + public static Map<String, String> generateSchema(JAXBContext context) throws IOException { + StringResolverImpl resolver = new StringResolverImpl(); + context.generateSchema(resolver); + Map<String, String> xsds = new HashMap<String, String>(); + for (Map.Entry<String, StreamResult> xsd : resolver.getResults().entrySet()) { + xsds.put(xsd.getKey(), xsd.getValue().getWriter().toString()); + } + return xsds; + } + + private static class XSDResolver implements URIResolver { + private Map<String, String> xsds; + + public XSDResolver(Map<String, String> xsds) { + super(); + this.xsds = xsds; + } + + public InputSource resolveEntity(java.lang.String namespace, + java.lang.String schemaLocation, + java.lang.String baseUri) { + String xsd = xsds.get(schemaLocation); + if (xsd == null) { + return null; + } + return new InputSource(new StringReader(xsd)); + } + + } + + /* + private void generateJAXBSchemas1(List<XSDefinition> definitions, XSDFactory factory) { + if (types.size() > 0) { + try { + XmlSchemaCollection collection = new XmlSchemaCollection(); + Class[] typesArray = new Class[types.size()]; + typesArray = types.toArray(typesArray); + JAXBContext context = JAXBContextHelper.createJAXBContext(typesArray); + Map<String, String> results = generateSchema(context); + collection.setSchemaResolver(new XSDResolver(results)); + + for (Map.Entry<String, String> entry : results.entrySet()) { + XSDefinition definition = factory.createXSDefinition(); + int index = entry.getKey().lastIndexOf('#'); + String ns = entry.getKey().substring(0, index); + String file = entry.getKey().substring(index + 1); + definition.setUnresolved(true); + definition.setNamespace(ns); + definition.setSchema(collection.read(new StringReader(entry.getValue()), null)); + definition.setSchemaCollection(collection); + definition.setUnresolved(false); + definitions.add(definition); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + */ + + private static class DOMResolverImpl extends SchemaOutputResolver { + private Map<String, DOMResult> results = new HashMap<String, DOMResult>(); + + @Override + public Result createOutput(String ns, String file) throws IOException { + DOMResult result = new DOMResult(); + // TUSCANY-2498: Set the system id to "" so that the xsd:import doesn't produce + // an illegal schemaLocation attr + result.setSystemId(""); + results.put(ns, result); + return result; + } + + public Map<String, DOMResult> getResults() { + return results; + } + } + + /* + private void generateJAXBSchemas(List<XSDefinition> definitions, XSDFactory factory) { + if (types.size() > 0) { + try { + Class<?>[] typesArray = new Class<?>[types.size()]; + typesArray = types.toArray(typesArray); + JAXBContext context = JAXBContext.newInstance(typesArray); + generateSchemas(definitions, factory, context); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + */ + + private void generateSchemas(List<XSDefinition> definitions, XSDFactory factory, JAXBContext context) + throws IOException { + DOMResolverImpl resolver = new DOMResolverImpl(); + context.generateSchema(resolver); + Map<String, DOMResult> results = resolver.getResults(); + for (Map.Entry<String, DOMResult> entry : results.entrySet()) { + XSDefinition definition = factory.createXSDefinition(); + definition.setUnresolved(true); + definition.setDocument((Document)entry.getValue().getNode()); + definition.setNamespace(entry.getKey()); + URI location = null; + try { + location = new URI(entry.getValue().getSystemId()); + } catch (URISyntaxException e) { + // ignore: use null value + } + definition.setLocation(location); + definitions.add(definition); + } + } + + private static class StringResolverImpl extends SchemaOutputResolver { + private Map<String, StreamResult> results = new HashMap<String, StreamResult>(); + + @Override + public Result createOutput(String ns, String file) throws IOException { + StringWriter sw = new StringWriter(); + StreamResult result = new StreamResult(sw); + String sysId = ns + '#' + file; + result.setSystemId(sysId); + results.put(sysId, result); + return result; + } + + public Map<String, StreamResult> getResults() { + return results; + } + } + + public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, Interface intf) { + try { + JAXBContext context = JAXBContextHelper.createJAXBContext(intf, false); + List<XSDefinition> definitions = new ArrayList<XSDefinition>(); + generateSchemas(definitions, factory, context); + return definitions; + } catch (Throwable e) { + throw new ServiceRuntimeException(e); + } + } + + public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, List<DataType> dataTypes) { + try { + + JAXBContext context = JAXBContextHelper.createJAXBContext(dataTypes); + List<XSDefinition> definitions = new ArrayList<XSDefinition>(); + generateSchemas(definitions, factory, context); + return definitions; + } catch (Throwable e) { + throw new ServiceRuntimeException(e); + } + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperException.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperException.java new file mode 100644 index 0000000000..f83c7f09d9 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperException.java @@ -0,0 +1,56 @@ +/* + * 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.databinding.jaxb; + +import org.osoa.sca.ServiceRuntimeException; + +public class JAXBWrapperException extends ServiceRuntimeException { + private static final long serialVersionUID = 1L; + + /** + * + */ + public JAXBWrapperException() { + super(); + + } + + /** + * @param message + * @param cause + */ + public JAXBWrapperException(String message, Throwable cause) { + super(message, cause); + + } + + /** @param message */ + public JAXBWrapperException(String message) { + super(message); + + } + + /** @param cause */ + public JAXBWrapperException(Throwable cause) { + super(cause); + + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandler.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandler.java new file mode 100644 index 0000000000..a1f4c12c8f --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandler.java @@ -0,0 +1,151 @@ +/* + * 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.databinding.jaxb; + +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; + +/** + * JAXB WrapperHandler implementation + * + * @version $Rev$ $Date$ + */ +public class JAXBWrapperHandler implements WrapperHandler<Object> { + private JAXBWrapperHelper helper = new JAXBWrapperHelper(); + + public Object create(Operation operation, boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + final Class<?> wrapperClass = input ? wrapperInfo.getInputWrapperClass() : wrapperInfo.getOutputWrapperClass(); + try { + if (wrapperClass == null) { + return null; + } + return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws Exception { + return wrapperClass.newInstance(); + } + }); + } catch (PrivilegedActionException e) { + throw new TransformationException(e); + } + } + + public void setChildren(Object wrapper, Object[] childObjects, Operation operation, boolean input) { + List<ElementInfo> childElements = + input ? operation.getWrapper().getInputChildElements() : operation.getWrapper().getOutputChildElements(); + List<String> childNames = new ArrayList<String>(); + Map<String, Object> values = new HashMap<String, Object>(); + for (int i = 0; i < childElements.size(); i++) { + ElementInfo e = childElements.get(i); + String name = e.getQName().getLocalPart(); + childNames.add(name); + values.put(name, childObjects[i]); + } + // Get the property descriptor map + Map<String, JAXBPropertyDescriptor> pdMap = null; + try { + pdMap = XMLRootElementUtil.createPropertyDescriptorMap(wrapper.getClass()); + } catch (Throwable t) { + throw new JAXBWrapperException(t); + } + helper.wrap(wrapper, childNames, values, pdMap); + } + + public void setChild(Object wrapper, int i, ElementInfo childElement, Object value) { + Object wrapperValue = wrapper; + Class<?> wrapperClass = wrapperValue.getClass(); + + // FIXME: We probably should use the jaxb-reflection to handle the properties + try { + String prop = childElement.getQName().getLocalPart(); + boolean collection = (value instanceof Collection); + Method getter = null; + for (Method m : wrapperClass.getMethods()) { + Class<?>[] paramTypes = m.getParameterTypes(); + if (paramTypes.length == 1 && m.getName().equals("set" + capitalize(prop))) { + m.invoke(wrapperValue, new Object[] {value}); + return; + } + if (collection && paramTypes.length == 0 && m.getName().equals("get" + capitalize(prop))) { + getter = m; + } + } + if (getter != null && Collection.class.isAssignableFrom(getter.getReturnType())) { + ((Collection)getter.invoke(wrapperValue)).addAll((Collection)value); + } + + } catch (Throwable e) { + throw new TransformationException(e); + } + } + + private static String capitalize(String name) { + char first = Character.toUpperCase(name.charAt(0)); + return first + name.substring(1); + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getChildren(java.lang.Object, Operation, boolean) + */ + public List getChildren(Object wrapper, Operation operation, boolean input) { + List<ElementInfo> childElements = input? operation.getWrapper().getInputChildElements(): + operation.getWrapper().getOutputChildElements(); + + List<String> childNames = new ArrayList<String>(); + for (ElementInfo e : childElements) { + childNames.add(e.getQName().getLocalPart()); + } + return Arrays.asList(helper.unwrap(wrapper, childNames)); + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getWrapperType(Operation, boolean) + */ + public DataType getWrapperType(Operation operation, boolean input) { + WrapperInfo wrapper = operation.getWrapper(); + DataType dt = input ? wrapper.getInputWrapperType() : wrapper.getOutputWrapperType(); + return dt; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#isInstance(java.lang.Object, Operation, boolean) + */ + public boolean isInstance(Object wrapper, Operation operation, boolean input) { + Class<?> wrapperClass = + input ? operation.getWrapper().getInputWrapperClass() : operation.getWrapper().getOutputWrapperClass(); + return wrapperClass == null ? false : wrapperClass.isInstance(wrapper); + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHelper.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHelper.java new file mode 100644 index 0000000000..5f90aa4d7a --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHelper.java @@ -0,0 +1,166 @@ +/* + * 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.databinding.jaxb; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * The JAXBWrapper tool is used to create a JAXB Object from a series of child objects (wrap) or get + * the child objects from a JAXB Object (unwrap) + */ +public class JAXBWrapperHelper { + + /** + * unwrap Returns the list of child objects of the jaxb object + * + * @param jaxbObject that represents the type + * @param childNames list of xml child names as String + * @param pdMap PropertyDescriptor map for this jaxbObject + * @return list of Objects in the same order as the element names. + */ + public Object[] unwrap(Object jaxbObject, List<String> childNames, Map<String, JAXBPropertyDescriptor> pdMap) + throws JAXBWrapperException { + + // Get the object that will have the property descriptors (i.e. the object representing the complexType) + Object jaxbComplexTypeObj = jaxbObject; + + // Get the PropertyDescriptorPlus map. + // The method makes sure that each child name has a matching jaxb property + // checkPropertyDescriptorMap(jaxbComplexTypeObj.getClass(), childNames, pdMap); + + // Get the corresponsing objects from the jaxb bean + ArrayList<Object> objList = new ArrayList<Object>(); + int index = 0; + for (String childName : childNames) { + JAXBPropertyDescriptor propInfo = getPropertyDescriptor(pdMap, childName, index); + + Object object = null; + try { + object = propInfo.get(jaxbComplexTypeObj); + } catch (Throwable e) { + throw new JAXBWrapperException(e); + } + + objList.add(object); + index++; + } + Object[] jaxbObjects = objList.toArray(); + objList = null; + return jaxbObjects; + + } + + private JAXBPropertyDescriptor getPropertyDescriptor(Map<String, JAXBPropertyDescriptor> pdMap, + String childName, + int index) { + JAXBPropertyDescriptor propInfo = pdMap.get(childName); + if (propInfo == null) { + // FIXME: [rfeng] Sometimes the child element names don't match. Get chilld by location? + List<JAXBPropertyDescriptor> props = new ArrayList<JAXBPropertyDescriptor>(pdMap.values()); + // Sort the properties by index. We might need to take propOrder into consideration + Collections.sort(props); + propInfo = props.get(index); + } + return propInfo; + } + + /** + * wrap Creates a jaxb object that is initialized with the child objects. + * <p/> + * Note that the jaxbClass must be the class the represents the complexType. (It should never be + * JAXBElement) + * + * @param jaxbClass + * @param childNames list of xml child names as String + * @param childObjects, component type objects + * @param pdMap PropertyDescriptor map for this jaxbObject + */ + public Object wrap(Class<?> jaxbClass, + List<String> childNames, + Map<String, Object> childObjects, + Map<String, JAXBPropertyDescriptor> pdMap) throws JAXBWrapperException { + + // Just like unWrap, get the property info map + // checkPropertyDescriptorMap(jaxbClass, childNames, pdMap); + + // The jaxb object always has a default constructor. Create the object + Object jaxbObject = null; + try { + jaxbObject = jaxbClass.newInstance(); + } catch (Throwable t) { + throw new JAXBWrapperException(t); + } + + wrap(jaxbObject, childNames, childObjects, pdMap); + + // Return the jaxb object + return jaxbObject; + } + + public void wrap(Object jaxbObject, + List<String> childNames, + Map<String, Object> childObjects, + Map<String, JAXBPropertyDescriptor> pdMap) { + // Now set each object onto the jaxb object + int index = 0; + for (String childName : childNames) { + JAXBPropertyDescriptor propInfo = getPropertyDescriptor(pdMap, childName, index); + Object value = childObjects.get(childName); + try { + propInfo.set(jaxbObject, value); + } catch (Throwable t) { + throw new JAXBWrapperException(t); + } + index++; + } + } + + public Object[] unwrap(Object jaxbObject, List<String> childNames) throws JAXBWrapperException { + // Get the property descriptor map for this JAXBClass + Class<?> jaxbClass = jaxbObject.getClass(); + Map<String, JAXBPropertyDescriptor> pdMap = null; + try { + pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass); + } catch (Throwable t) { + throw new JAXBWrapperException(t); + } + + // Delegate + return unwrap(jaxbObject, childNames, pdMap); + } + + public Object wrap(Class<?> jaxbClass, List<String> childNames, Map<String, Object> childObjects) + throws JAXBWrapperException { + // Get the property descriptor map + Map<String, JAXBPropertyDescriptor> pdMap = null; + try { + pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass); + } catch (Throwable t) { + throw new JAXBWrapperException(t); + } + + // Delegate + return wrap(jaxbClass, childNames, childObjects, pdMap); + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Node2JAXB.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Node2JAXB.java new file mode 100644 index 0000000000..e375a9b85e --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Node2JAXB.java @@ -0,0 +1,73 @@ +/* + * 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.databinding.jaxb; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * + * @version $Rev$ $Date$ + */ +public class Node2JAXB extends BaseTransformer<Node, Object> implements PullTransformer<Node, Object> { + + public Node2JAXB() { + super(); + } + + public Object transform(Node source, TransformationContext context) { + if (source == null) + return null; + try { + JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + Object result = unmarshaller.unmarshal(source, JAXBContextHelper.getJavaType(context.getTargetDataType())); + return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + @Override + public int getWeight() { + return 30; + } + + @Override + public String getTargetDataBinding() { + return JAXBDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Reader2JAXB.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Reader2JAXB.java new file mode 100644 index 0000000000..840edfd234 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Reader2JAXB.java @@ -0,0 +1,74 @@ +/* + * 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.databinding.jaxb; + +import java.io.Reader; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * + * @version $Rev$ $Date$ + */ +public class Reader2JAXB extends BaseTransformer<Reader, Object> implements + PullTransformer<Reader, Object> { + + public Object transform(final Reader source, final TransformationContext context) { + if (source == null) { + return null; + } + try { + JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + StreamSource streamSource = new StreamSource(source); + Object result = unmarshaller.unmarshal(streamSource, JAXBContextHelper.getJavaType(context.getTargetDataType())); + return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Reader> getSourceType() { + return Reader.class; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + @Override + public int getWeight() { + return 30; + } + + @Override + public String getTargetDataBinding() { + return JAXBDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/String2JAXB.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/String2JAXB.java new file mode 100644 index 0000000000..5559690de8 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/String2JAXB.java @@ -0,0 +1,80 @@ +/* + * 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.databinding.jaxb; + +import java.io.StringReader; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.xml.XMLStringDataBinding; + +/** + * + * @version $Rev$ $Date$ + */ +public class String2JAXB extends BaseTransformer<String, Object> implements + PullTransformer<String, Object> { + + public Object transform(final String source, final TransformationContext context) { + if (source == null) { + return null; + } + try { + JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + StreamSource streamSource = new StreamSource(new StringReader(source)); + Object result = unmarshaller.unmarshal(streamSource, JAXBContextHelper.getJavaType(context.getTargetDataType())); + return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + @Override + public int getWeight() { + return 30; + } + + @Override + public String getSourceDataBinding() { + return XMLStringDataBinding.NAME; + } + + @Override + public String getTargetDataBinding() { + return JAXBDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLAdapterExtensionPoint.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLAdapterExtensionPoint.java new file mode 100644 index 0000000000..5fa98b5ed1 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLAdapterExtensionPoint.java @@ -0,0 +1,52 @@ +/* + * 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.databinding.jaxb; + +import java.util.Map; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +/** + * @version $Rev$ $Date$ + */ +public interface XMLAdapterExtensionPoint { + /** + * @param boundType + * @param adapter + */ + void addAdapter(Class<?> boundType, Class<? extends XmlAdapter> adapter); + + /** + * @param boundType + * @return + */ + Class<? extends XmlAdapter> getAdapter(Class<?> boundType); + + /** + * @param boundType + * @return + */ + Class<? extends XmlAdapter> removeAdapter(Class<?> boundType); + + /** + * @return + */ + Map<Class<?>, Class<? extends XmlAdapter>> getAdapters(); +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLRootElementUtil.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLRootElementUtil.java new file mode 100644 index 0000000000..ad4bd04084 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLRootElementUtil.java @@ -0,0 +1,286 @@ +/* + * 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.databinding.jaxb; + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.namespace.QName; + +/** + * + */ +public class XMLRootElementUtil { + + /** Constructor is intentionally private. This class only provides static utility methods */ + private XMLRootElementUtil() { + + } + + /** + * @param clazz + * @return namespace of root element qname or null if this is not object does not represent a + * root element + */ + public static QName getXmlRootElementQNameFromObject(Object obj) { + + // A JAXBElement stores its name + if (obj instanceof JAXBElement) { + return ((JAXBElement<?>)obj).getName(); + } + + Class<?> clazz = (obj instanceof java.lang.Class) ? (Class<?>)obj : obj.getClass(); + return getXmlRootElementQName(clazz); + } + + /** + * @param clazz + * @return namespace of root element qname or null if this is not object does not represent a + * root element + */ + public static QName getXmlRootElementQName(Class<?> clazz) { + + // See if the object represents a root element + XmlRootElement root = (XmlRootElement)getAnnotation(clazz, XmlRootElement.class); + if (root == null) { + return null; + } + + String name = root.name(); + String namespace = root.namespace(); + + // The name may need to be defaulted + if (name == null || name.length() == 0 || name.equals("##default")) { + name = getSimpleName(clazz.getCanonicalName()); + } + + // The namespace may need to be defaulted + if (namespace == null || namespace.length() == 0 || namespace.equals("##default")) { + Package pkg = clazz.getPackage(); + XmlSchema schema = (XmlSchema)getAnnotation(pkg, XmlSchema.class); + if (schema != null) { + namespace = schema.namespace(); + } else { + namespace = ""; + } + } + + return new QName(namespace, name); + } + + /** + * @param clazz + * @return namespace of root element qname or null if this is not object does not represent a root element + */ + public static String getEnumValue(Enum<?> myEnum) { + Field f; + String value; + try { + f = myEnum.getClass().getField(myEnum.name()); + + f.setAccessible(true); + + XmlEnumValue xev = (XmlEnumValue)getAnnotation(f, XmlEnumValue.class); + if (xev == null) { + value = f.getName(); + } else { + value = xev.value(); + } + } catch (SecurityException e) { + value = null; + } catch (NoSuchFieldException e) { + value = null; + } + + return value; + } + + /** + * utility method to get the last token in a "."-delimited package+classname string + * + * @return + */ + private static String getSimpleName(String in) { + if (in == null || in.length() == 0) { + return in; + } + String out = null; + StringTokenizer tokenizer = new StringTokenizer(in, "."); + if (tokenizer.countTokens() == 0) + out = in; + else { + while (tokenizer.hasMoreTokens()) { + out = tokenizer.nextToken(); + } + } + return out; + } + + /** + * The JAXBClass has a set of bean properties each represented by a PropertyDescriptor Each of + * the fields of the class has an associated xml name. The method returns a map where the key is + * the xml name and value is the PropertyDescriptor + * + * @param jaxbClass + * @return map + */ + public static Map<String, JAXBPropertyDescriptor> createPropertyDescriptorMap(Class<?> jaxbClass) + throws NoSuchFieldException, IntrospectionException { + + PropertyDescriptor[] pds = Introspector.getBeanInfo(jaxbClass).getPropertyDescriptors(); + Map<String, JAXBPropertyDescriptor> map = new HashMap<String, JAXBPropertyDescriptor>(); + + // Unfortunately the element names are stored on the fields. + // Get all of the fields in the class and super classes + + List<Field> fields = getFields(jaxbClass); + + // Now match up the fields with the property descriptors...Sigh why didn't JAXB put the @XMLElement annotations on the + // property methods! + for (PropertyDescriptor pd : pds) { + + // Skip over the class property..it is never represented as an xml element + if (pd.getName().equals("class")) { + continue; + } + + // For the current property, find a matching field...so that we can get the xml name + boolean found = false; + + int index = 0; + for (Field field : fields) { + String fieldName = field.getName(); + + // Use the name of the field and property to find the match + if (fieldName.equalsIgnoreCase(pd.getDisplayName()) || fieldName.equalsIgnoreCase(pd.getName())) { + // Get the xmlElement name for this field + QName xmlName = getXmlElementRefOrElementQName(field.getDeclaringClass(), field); + found = true; + map.put(xmlName.getLocalPart(), new JAXBPropertyDescriptor(pd, xmlName, index)); + index++; + break; + } + + // Unfortunately, sometimes the field name is preceeded by an underscore + if (fieldName.startsWith("_")) { + fieldName = fieldName.substring(1); + if (fieldName.equalsIgnoreCase(pd.getDisplayName()) || fieldName.equalsIgnoreCase(pd.getName())) { + // Get the xmlElement name for this field + QName xmlName = getXmlElementRefOrElementQName(field.getDeclaringClass(), field); + found = true; + + map.put(xmlName.getLocalPart(), new JAXBPropertyDescriptor(pd, xmlName, index)); + index++; + break; + } + } + } + + // We didn't find a field. Default the xmlname to the property name + if (!found) { + String xmlName = pd.getName(); + + map.put(xmlName, new JAXBPropertyDescriptor(pd, xmlName, index)); + index++; + } + + } + return map; + } + + /** + * Gets all of the fields in this class and the super classes + * + * @param beanClass + * @return + */ + static private List<Field> getFields(final Class<?> beanClass) { + // This class must remain private due to Java 2 Security concerns + List<Field> fields = AccessController.doPrivileged(new PrivilegedAction<List<Field>>() { + public List<Field> run() { + List<Field> fields = new ArrayList<Field>(); + Class<?> cls = beanClass; + while (cls != null) { + Field[] fieldArray = cls.getDeclaredFields(); + for (Field field : fieldArray) { + fields.add(field); + } + cls = cls.getSuperclass(); + } + return fields; + } + }); + + return fields; + } + + /** + * Get the name of the field by looking at the XmlElement annotation. + * + * @param jaxbClass + * @param fieldName + * @return + * @throws NoSuchFieldException + */ + private static QName getXmlElementRefOrElementQName(Class<?> jaxbClass, Field field) throws NoSuchFieldException { + XmlElementRef xmlElementRef = (XmlElementRef)getAnnotation(field, XmlElementRef.class); + if (xmlElementRef != null) { + return new QName(xmlElementRef.namespace(), xmlElementRef.name()); + } + XmlElement xmlElement = (XmlElement)getAnnotation(field, XmlElement.class); + + // If XmlElement does not exist, default to using the field name + if (xmlElement == null || xmlElement.name().equals("##default")) { + return new QName("", field.getName()); + } + return new QName(xmlElement.namespace(), xmlElement.name()); + } + + /** + * Get an annotation. This is wrappered to avoid a Java2Security violation. + * @param cls Class that contains annotation + * @param annotation Class of requrested Annotation + * @return annotation or null + */ + private static <T extends Annotation> T getAnnotation(final AnnotatedElement element, final Class<T> annotation) { + return AccessController.doPrivileged(new PrivilegedAction<T>() { + public T run() { + return element.getAnnotation(annotation); + } + }); + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLStreamReader2JAXB.java b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLStreamReader2JAXB.java new file mode 100644 index 0000000000..af3fa3fb66 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLStreamReader2JAXB.java @@ -0,0 +1,77 @@ +/* + * 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.databinding.jaxb; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2JAXB extends BaseTransformer<XMLStreamReader, Object> implements + PullTransformer<XMLStreamReader, Object> { + + public XMLStreamReader2JAXB() { + super(); + } + + public Object transform(XMLStreamReader source, TransformationContext context) { + if (source == null) { + return null; + } + try { + JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + // FIXME: [rfeng] If the java type is Object.class, the unmarshalled result will be + // a DOM Node + Object result = unmarshaller.unmarshal(source, JAXBContextHelper.getJavaType(context.getTargetDataType())); + source.close(); + return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + public Class<Object> getTargetType() { + return Object.class; + } + + @Override + public int getWeight() { + return 10; + } + + @Override + public String getTargetDataBinding() { + return JAXBDataBinding.NAME; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..58d6123373 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,19 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding;type=javax.xml.bind.JAXBElement,name=jaxb diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..4e062e4c22 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,32 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;source=javax.xml.bind.JAXBElement,target=org.w3c.dom.Node,weight=500 +org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;source=org.w3c.dom.Node,target=javax.xml.bind.JAXBElement,weight=500 +org.apache.tuscany.sca.databinding.jaxb.Reader2JAXB;source=java.io.Reader,target=javax.xml.bind.JAXBElement,weight=510 +org.apache.tuscany.sca.databinding.jaxb.XMLStreamReader2JAXB;source=javax.xml.stream.XMLStreamReader,target=javax.xml.bind.JAXBElement,weight=490 + +org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;source=java:complexType,target=org.w3c.dom.Node,weight=90000 +org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;source=org.w3c.dom.Node,target=java:complexType,weight=90000 + +org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;source=org.w3c.dom.Node,target=java:simpleType,weight=90000 +org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;source=java:simpleType,target=org.w3c.dom.Node,weight=90000 + +org.apache.tuscany.sca.databinding.jaxb.XMLStreamReader2JAXB;source=javax.xml.stream.XMLStreamReader,target=java:complexType,weight=90000 +org.apache.tuscany.sca.databinding.jaxb.XMLStreamReader2JAXB;source=javax.xml.stream.XMLStreamReader,target=java:simpleType,weight=90000 + diff --git a/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint b/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint new file mode 100644 index 0000000000..d1f6d9f1e3 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.databinding.jaxb.DefaultXMLAdapterExtensionPoint
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/com/example/stock/StockQuoteOffer.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/com/example/stock/StockQuoteOffer.java new file mode 100644 index 0000000000..5c5c892f33 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/com/example/stock/StockQuoteOffer.java @@ -0,0 +1,45 @@ +/* + * 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 com.example.stock; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * <p>Java class for anonymous complex type. + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = {"input"}) +@XmlRootElement(name = "stockQuoteOffer") +public class StockQuoteOffer { + + protected String input; + + public String getInput() { + return this.input; + } + + public void setInput(String input) { + this.input = input; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/BeanXMLStreamReaderImpl.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/BeanXMLStreamReaderImpl.java new file mode 100644 index 0000000000..602bc66569 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/BeanXMLStreamReaderImpl.java @@ -0,0 +1,324 @@ +/* + * 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.databinding.jaxb; + +import java.lang.reflect.Array; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.xml.SimpleXmlNodeImpl; +import org.apache.tuscany.sca.databinding.xml.XmlNode; +import org.apache.tuscany.sca.databinding.xml.XmlTreeStreamReaderImpl; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.jvnet.jaxb.reflection.model.annotation.RuntimeInlineAnnotationReader; +import org.jvnet.jaxb.reflection.model.core.Ref; +import org.jvnet.jaxb.reflection.model.impl.RuntimeModelBuilder; +import org.jvnet.jaxb.reflection.model.runtime.RuntimeClassInfo; +import org.jvnet.jaxb.reflection.model.runtime.RuntimePropertyInfo; +import org.jvnet.jaxb.reflection.model.runtime.RuntimeTypeInfoSet; +import org.jvnet.jaxb.reflection.runtime.IllegalAnnotationsException; +import org.jvnet.jaxb.reflection.runtime.JAXBContextImpl; + + + +/** + * @version $Rev$ $Date$ + */ +public class BeanXMLStreamReaderImpl extends XmlTreeStreamReaderImpl { + private static final Comparator<Accessor> COMPARATOR = new Comparator<Accessor>() { + public int compare(Accessor o1, Accessor o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + private static final String XSI_PREFIX = "xsi"; + private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance"; + + private static XmlNode getXSIType(QName realType) { + QName xsiType = new QName(XSI_NS, "type", XSI_PREFIX); + String prefix = realType.getPrefix(); + String typeName = realType.getLocalPart(); + if (prefix != null && !prefix.equals("")) { + typeName = prefix + ":" + realType.getLocalPart(); + } + return new SimpleXmlNodeImpl(xsiType, XmlNode.Type.ATTRIBUTE); + } + + /** + * Represent a Map.Entry XML node + * @version $Rev$ $Date$ + */ + public static class MapEntryXmlNodeImpl extends SimpleXmlNodeImpl implements XmlNode { + private Map.Entry entry; + + public MapEntryXmlNodeImpl(Entry entry) { + super(new QName("", "entry"), entry); + this.entry = entry; + } + + @Override + public Iterator<XmlNode> children() { + List<XmlNode> nodes = new ArrayList<XmlNode>(); + XmlNode key = new BeanXmlNodeImpl(new QName("", "key"), entry.getKey()); + XmlNode value = new BeanXmlNodeImpl(new QName("", "value"), entry.getValue()); + nodes.add(key); + nodes.add(value); + return nodes.iterator(); + } + } + + public static class BeanXmlNodeImpl extends SimpleXmlNodeImpl implements XmlNode { + private static final Object[] NULL = null; + private static final SimpleTypeMapperImpl MAPPER = new SimpleTypeMapperImpl(); + + public BeanXmlNodeImpl(Object bean) { + super(getName(bean == null ? null : bean.getClass()), bean); + } + + public BeanXmlNodeImpl(QName name, Object bean) { + super(name, bean); + } + + private static boolean isSimpleType(Class<?> javaType) { + return SimpleTypeMapperImpl.getXMLType(javaType) != null; + } + + private static String getStringValue(Object o) { + if (o == null) { + return null; + } + TypeInfo info = SimpleTypeMapperImpl.getXMLType(o.getClass()); + if (info != null) { + return MAPPER.toXMLLiteral(info.getQName(), o, null); + } else { + return String.valueOf(o); + } + } + + @Override + public Iterator<XmlNode> children() { + if (name == null) { + return null; + } + if (value == null) { + return super.children(); + } + if (isSimpleType(value.getClass())) { + XmlNode textNode = new BeanXmlNodeImpl(null, value); + return Arrays.asList(textNode).iterator(); + } + if (Map.class.isAssignableFrom(value.getClass())) { + List<XmlNode> entries = new ArrayList<XmlNode>(); + Map map = (Map)value; + if (map != null) { + for (Object e : map.entrySet()) { + Map.Entry entry = (Map.Entry)e; + entries.add(new MapEntryXmlNodeImpl(entry)); + } + } + return entries.iterator(); + } + try { + Map<String, Accessor> accessorMap = getAccessors(value); + List<Accessor> accessorList = new ArrayList<Accessor>(accessorMap.values()); + Collections.sort(accessorList, COMPARATOR); + + List<XmlNode> props = new ArrayList<XmlNode>(); + for (Accessor accessor : accessorList) { + Class<?> pType = accessor.getType(); + + QName pName = new QName(name.getNamespaceURI(), accessor.getName()); + Object pValue = accessor.getValue(); + if (pType.isArray()) { + if (pValue != null) { + int i1 = Array.getLength(pValue); + for (int j = 0; j < i1; j++) { + Object o = Array.get(pValue, j); + props.add(new BeanXmlNodeImpl(pName, o)); + } + } else { + // TODO: How to handle null? + } + } else if (Collection.class.isAssignableFrom(pType)) { + Collection objList = (Collection)pValue; + if (objList != null && objList.size() > 0) { + for (Iterator j = objList.iterator(); j.hasNext();) { + Object o = j.next(); + props.add(new BeanXmlNodeImpl(pName, o)); + } + + } else { + // How to handle null + } + } else { + props.add(new BeanXmlNodeImpl(pName, pValue)); + } + } + return props.iterator(); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public QName getName() { + return name; + } + + @Override + public String getValue() { + return getStringValue(value); + } + + private static String getPackageName(Class<?> cls) { + String name = cls.getName(); + int index = name.lastIndexOf('.'); + return index == -1 ? "" : name.substring(0, index); + } + + public static QName getName(Class<?> cls) { + if (cls == null) { + return null; + } + + String packageName = getPackageName(cls); + + if ("".equals(packageName)) { + return new QName("", cls.getSimpleName()); + } + StringBuffer ns = new StringBuffer("http://"); + String[] names = packageName.split("\\."); + for (int i = names.length - 1; i >= 0; i--) { + ns.append(names[i]); + if (i != 0) { + ns.append('.'); + } + } + ns.append('/'); + return new QName(ns.toString(), cls.getSimpleName()); + } + } + + public BeanXMLStreamReaderImpl(QName name, Object bean) { + super(getXmlNode(name, bean)); + } + + private static BeanXmlNodeImpl getXmlNode(QName name, Object bean) { + BeanXmlNodeImpl root = null; + if (name != null) { + root = new BeanXmlNodeImpl(name, bean); + } else { + root = new BeanXmlNodeImpl(bean); + } + return root; + } + + public static interface Accessor { + String getName(); + + Class<?> getType(); + + Object getValue() throws Exception; + + void setValue(Object value) throws Exception; + } + + private static RuntimeTypeInfoSet create(Class... classes) throws Exception { + IllegalAnnotationsException.Builder errorListener = new IllegalAnnotationsException.Builder(); + RuntimeInlineAnnotationReader reader = new RuntimeInlineAnnotationReader(); + JAXBContextImpl context = + new JAXBContextImpl(classes, null, Collections.<Class, Class> emptyMap(), null, false, reader, false, false); + RuntimeModelBuilder builder = + new RuntimeModelBuilder(context, reader, Collections.<Class, Class> emptyMap(), null); + builder.setErrorHandler(errorListener); + for (Class c : classes) + builder.getTypeInfo(new Ref<Type, Class>(c)); + + RuntimeTypeInfoSet r = builder.link(); + errorListener.check(); + return r; + } + + private static class JAXBAccessor implements Accessor { + private Object target; + private RuntimePropertyInfo prop; + + public JAXBAccessor(Object target, RuntimePropertyInfo field) { + super(); + this.target = target; + this.prop = field; + } + + public String getName() { + return prop.getName(); + } + + public Object getValue() throws Exception { + return prop.getAccessor().get(target); + } + + public void setValue(Object value) throws Exception { + prop.getAccessor().set(target, value); + } + + public Class<?> getType() { + Type type = prop.getRawType(); + if (type instanceof Class) { + return (Class<?>)type; + } else if (type instanceof ParameterizedType) { + ParameterizedType pType = (ParameterizedType)type; + type = pType.getRawType(); + if (type instanceof Class) { + return (Class<?>)type; + } + } + return Object.class; + } + + } + + private static Map<String, Accessor> getAccessors(Object target) throws Exception { + if (target == null) { + return Collections.emptyMap(); + } + Map<String, Accessor> map = new HashMap<String, Accessor>(); + Class<?> type = target.getClass(); + RuntimeTypeInfoSet set = create(type); + RuntimeClassInfo clsInfo = (RuntimeClassInfo)set.getTypeInfo(type); + for (RuntimePropertyInfo f : clsInfo.getProperties()) { + map.put(f.getName(), new JAXBAccessor(target, f)); + } + return map; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2XMLStreamReader.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2XMLStreamReader.java new file mode 100644 index 0000000000..e2151e23a1 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2XMLStreamReader.java @@ -0,0 +1,84 @@ +/* + * 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.databinding.jaxb; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * + * @version $Rev$ $Date$ + */ +public class JAXB2XMLStreamReader extends BaseTransformer<Object, XMLStreamReader> implements + PullTransformer<Object, XMLStreamReader> { + + public JAXB2XMLStreamReader() { + super(); + } + + public XMLStreamReader transform(Object source, TransformationContext context) { + if (source == null) { + return null; + } + try { + QName name = null; + Object bean = null; + if (source instanceof JAXBElement) { + bean = ((JAXBElement)source).getValue(); + name = ((JAXBElement)source).getName(); + } else { + JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, true); + Object element = JAXBContextHelper.createJAXBElement(jaxbContext, context.getSourceDataType(), source); + name = jaxbContext.createJAXBIntrospector().getElementName(element); + bean = source; + } + BeanXMLStreamReaderImpl reader = new BeanXMLStreamReaderImpl(name, bean); + return reader; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 10; + } + + @Override + public String getTargetDataBinding() { + return JAXBDataBinding.NAME; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCacheTestCase.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCacheTestCase.java new file mode 100644 index 0000000000..761414e92b --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCacheTestCase.java @@ -0,0 +1,123 @@ +/* + * 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.databinding.jaxb; + +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextCache; +import org.apache.tuscany.sca.databinding.util.LRUCache; +import org.junit.Test; + +import com.example.ipo.jaxb.Address; +import com.example.ipo.jaxb.PurchaseOrderType; + +/** + * @version $Rev$ $Date$ + */ +public class JAXBContextCacheTestCase { + @Test + public void testCache() throws JAXBException { + JAXBContextCache cache = new JAXBContextCache(); + JAXBContext context1 = cache.getJAXBContext(String.class); + JAXBContext context2 = cache.getJAXBContext(int.class); + JAXBContext context3 = cache.getJAXBContext(String[].class); + JAXBContext context4 = cache.getJAXBContext(Source.class); + Assert.assertSame(context1, context2); + Assert.assertNotSame(context2, context3); + Assert.assertSame(context1, context4); + + QName name = new QName("http://example.com/ns1", "e1"); + JAXBElement<String> element = new JAXBElement<String>(name, String.class, "123"); + StringWriter sw = new StringWriter(); + context4.createMarshaller().marshal(element, sw); + StreamSource source = new StreamSource(new StringReader(sw.toString()), null); + context4.createUnmarshaller().unmarshal(source, String.class); + + JAXBContext context5 = cache.getJAXBContext(Address.class); + JAXBContext context6 = cache.getJAXBContext(PurchaseOrderType.class); + Assert.assertSame(context5, context6); + } + + @Test + public void testLRUCache() { + LRUCache<String, String> cache = new LRUCache<String, String>(3); + cache.put("1", "A"); + Assert.assertEquals(1, cache.size()); + cache.put("2", "B"); + Assert.assertEquals(2, cache.size()); + cache.put("3", "C"); + Assert.assertEquals(3, cache.size()); + cache.put("4", "D"); + Assert.assertEquals(3, cache.size()); + String data = cache.get("1"); + Assert.assertNull(data); + data = cache.get("2"); + Assert.assertEquals("B", data); + cache.put("5", "E"); + data = cache.get("2"); + Assert.assertEquals("B", data); + } + + @Test + public void testPerf() throws JAXBException { + JAXBContextCache cache = new JAXBContextCache(); + + // Test JAXBContext for simple java classes + long start = System.currentTimeMillis(); + for (int i = 0; i < 100; i++) { + JAXBContext context = JAXBContext.newInstance(String.class); + } + long end = System.currentTimeMillis(); + long d1 = end - start; + start = System.currentTimeMillis(); + for (int i = 0; i < 100; i++) { + JAXBContext context = cache.getJAXBContext(String.class); + } + end = System.currentTimeMillis(); + long d2 = end - start; + System.out.println(d1 + "ms vs. " + d2 + "ms"); + + // Test JAXBContext for generated JAXB classes + start = System.currentTimeMillis(); + for (int i = 0; i < 20; i++) { + JAXBContext context = JAXBContext.newInstance(PurchaseOrderType.class); + } + end = System.currentTimeMillis(); + d1 = end - start; + start = System.currentTimeMillis(); + for (int i = 0; i < 20; i++) { + JAXBContext context = cache.getJAXBContext(PurchaseOrderType.class); + } + end = System.currentTimeMillis(); + d2 = end - start; + System.out.println(d1 + "ms vs. " + d2 + "ms"); + + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBindingTestCase.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBindingTestCase.java new file mode 100644 index 0000000000..5452175c54 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBindingTestCase.java @@ -0,0 +1,130 @@ +/* + * 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.databinding.jaxb; + +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import com.example.ipo.jaxb.ObjectFactory; +import com.example.ipo.jaxb.PurchaseOrderType; +import com.example.ipo.jaxb.USAddress; +import com.example.ipo.jaxb.USState; + +/** + * + * @version $Rev$ $Date$ + */ +public class JAXBDataBindingTestCase extends TestCase { + private JAXBDataBinding binding; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + binding = new JAXBDataBinding(); + } + + /** + * Test method for + * {@link org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding#introspect(java.lang.Class, Operation)}. + */ + public final void testIntrospect() { + DataType dataType = new DataTypeImpl<Class>(JAXBElement.class, null); + Operation op = null; + boolean yes = binding.introspect(dataType, op); + assertTrue(yes); + assertTrue(dataType.getDataBinding().equals(binding.getName())); + assertTrue(dataType.getPhysical() == JAXBElement.class && dataType.getLogical() == XMLType.UNKNOWN); + dataType = new DataTypeImpl<Class>(MockJAXBElement.class, null); + yes = binding.introspect(dataType, op); + assertTrue(yes); + assertEquals(MockJAXBElement.class, dataType.getPhysical()); + assertEquals(new QName("http://www.example.com/IPO", "PurchaseOrderType"), ((XMLType)dataType.getLogical()) + .getTypeName()); + dataType = new DataTypeImpl<Class>(USAddress.class, null); + yes = binding.introspect(dataType, op); + assertTrue(yes); + assertEquals(USAddress.class, dataType.getPhysical()); + assertEquals(new QName("http://www.example.com/IPO", "USAddress"), ((XMLType)dataType.getLogical()) + .getTypeName()); + dataType = new DataTypeImpl<Class>(USState.class, null); + yes = binding.introspect(dataType, op); + assertTrue(yes); + assertTrue(dataType.getDataBinding().equals(binding.getName())); + assertEquals(USState.class, dataType.getPhysical()); + assertEquals(new QName("http://www.example.com/IPO", "USState"), ((XMLType)dataType.getLogical()).getTypeName()); + + } + + private static class MockJAXBElement extends JAXBElement<PurchaseOrderType> { + + private static final long serialVersionUID = -2767569071002707973L; + + /** + * @param elementName + * @param type + * @param value + */ + public MockJAXBElement(QName elementName, Class<PurchaseOrderType> type, PurchaseOrderType value) { + super(elementName, type, value); + } + + } + + @SuppressWarnings("unchecked") + public void testCopy() { + ObjectFactory factory = new ObjectFactory(); + PurchaseOrderType poType = factory.createPurchaseOrderType(); + JAXBElement<PurchaseOrderType> po = factory.createPurchaseOrder(poType); + JAXBElement<PurchaseOrderType> copy = (JAXBElement<PurchaseOrderType>)binding.copy(po, null, null); + assertEquals(new QName("http://www.example.com/IPO", "purchaseOrder"), copy.getName()); + } + + @SuppressWarnings("unchecked") + public void testCopyNonElement() { + ObjectFactory factory = new ObjectFactory(); + PurchaseOrderType poType = factory.createPurchaseOrderType(); + poType.setComment("Comment"); + PurchaseOrderType copy = (PurchaseOrderType)binding.copy(poType, null, null); + assertTrue(copy instanceof PurchaseOrderType); + assertEquals("Comment", (copy).getComment()); + } + + @SuppressWarnings("unchecked") + public void testCopyNonRoot() { + ObjectFactory factory = new ObjectFactory(); + USAddress address = factory.createUSAddress(); + address.setCity("San Jose"); + USAddress copy = (USAddress)binding.copy(address, null, null); + assertTrue(copy instanceof USAddress); + assertEquals("San Jose", (copy).getCity()); + + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBReflectionTestCase.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBReflectionTestCase.java new file mode 100644 index 0000000000..cbc32d4353 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBReflectionTestCase.java @@ -0,0 +1,94 @@ +/* + * 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.databinding.jaxb; + +import java.lang.reflect.Type; +import java.util.Collections; + +import javax.xml.bind.JAXBContext; +import javax.xml.namespace.QName; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; +import org.apache.tuscany.sca.databinding.xml.Node2String; +import org.jvnet.jaxb.reflection.model.annotation.RuntimeInlineAnnotationReader; +import org.jvnet.jaxb.reflection.model.core.Ref; +import org.jvnet.jaxb.reflection.model.impl.RuntimeModelBuilder; +import org.jvnet.jaxb.reflection.model.runtime.RuntimeClassInfo; +import org.jvnet.jaxb.reflection.model.runtime.RuntimePropertyInfo; +import org.jvnet.jaxb.reflection.model.runtime.RuntimeTypeInfoSet; +import org.jvnet.jaxb.reflection.runtime.IllegalAnnotationsException; +import org.jvnet.jaxb.reflection.runtime.JAXBContextImpl; +import org.w3c.dom.Node; + +import com.example.ipo.jaxb.ObjectFactory; +import com.example.ipo.jaxb.PurchaseOrderType; +import com.example.ipo.jaxb.USAddress; +import com.example.ipo.jaxb.USState; + +/** + * @version $Rev$ $Date$ + */ +public class JAXBReflectionTestCase extends TestCase { + + public void testGenerateSchema() throws Exception { + JAXBContext context = JAXBContext.newInstance("com.example.ipo.jaxb"); + Node schema = JAXBContextHelper.generateSchema(context); + System.out.println(new Node2String().transform(schema, null)); + } + + /** + * This is a workaround for the NPE bug in jaxb-reflection + * @param classes + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + private static RuntimeTypeInfoSet create(Class... classes) throws Exception { + IllegalAnnotationsException.Builder errorListener = new IllegalAnnotationsException.Builder(); + RuntimeInlineAnnotationReader reader = new RuntimeInlineAnnotationReader(); + JAXBContextImpl context = + new JAXBContextImpl(classes, null, Collections.<Class, Class> emptyMap(), null, false, reader, false, false); + RuntimeModelBuilder builder = + new RuntimeModelBuilder(context, reader, Collections.<Class, Class> emptyMap(), null); + builder.setErrorHandler(errorListener); + for (Class c : classes) + builder.getTypeInfo(new Ref<Type, Class>(c)); + + RuntimeTypeInfoSet r = builder.link(); + errorListener.check(); + return r; + } + + public void testReflection() throws Exception { + org.jvnet.jaxb.reflection.model.runtime.RuntimeTypeInfoSet model = create(PurchaseOrderType.class); + RuntimeClassInfo type = (RuntimeClassInfo)model.getTypeInfo(PurchaseOrderType.class); + Assert.assertEquals(new QName("http://www.example.com/IPO", "PurchaseOrderType"), type.getTypeName()); + type = (RuntimeClassInfo)model.getTypeInfo(USAddress.class); + Assert.assertEquals(new QName("http://www.example.com/IPO", "USAddress"), type.getTypeName()); + RuntimePropertyInfo prop = type.getProperty("state"); + Assert.assertNotNull(prop); + USAddress address = new ObjectFactory().createUSAddress(); + prop.getAccessor().set(address, USState.CA); + Assert.assertEquals(USState.CA, address.getState()); + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTestCase.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTestCase.java new file mode 100644 index 0000000000..53779a1af6 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTestCase.java @@ -0,0 +1,175 @@ +/* + * 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.databinding.jaxb; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.io.StringReader; + +import javax.xml.namespace.QName; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.jaxb.JAXB2Node; +import org.apache.tuscany.sca.databinding.jaxb.Node2JAXB; +import org.apache.tuscany.sca.databinding.jaxb.Reader2JAXB; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Node; + +import com.example.ipo.jaxb.ObjectFactory; +import com.example.ipo.jaxb.PurchaseOrderType; + +/** + * + * @version $Rev$ $Date$ + */ +public class JAXBTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransform() throws Exception { + Reader2JAXB t0 = new Reader2JAXB(); + + DataType targetDataType = new DataTypeImpl<Class>(PurchaseOrderType.class, null); + + TransformationContext tContext = createMock(TransformationContext.class); + expect(tContext.getTargetDataType()).andReturn(targetDataType).anyTimes(); + expect(tContext.getTargetOperation()).andReturn(null).anyTimes(); + replay(tContext); + + Object object1 = t0.transform(new StringReader(IPO_XML), tContext); + + DataType sourceDataType = new DataTypeImpl<Class>(PurchaseOrderType.class, null); + + TransformationContext tContext1 = createMock(TransformationContext.class); + expect(tContext1.getSourceDataType()).andReturn(sourceDataType).anyTimes(); + expect(tContext1.getTargetDataType()).andReturn(null).anyTimes(); + expect(tContext1.getSourceOperation()).andReturn(null).anyTimes(); + expect(tContext1.getTargetOperation()).andReturn(null).anyTimes(); + replay(tContext1); + + JAXB2Node t1 = new JAXB2Node(); + Node node = t1.transform(object1, tContext1); + + Assert.assertNotNull(node); + + Node2JAXB t2 = new Node2JAXB(); + Object object2 = t2.transform(node, tContext); + Assert.assertNotNull(object2); + + } + + public void testTransform2() throws Exception { + Reader2JAXB t0 = new Reader2JAXB(); + + QName root = new QName("http://www.example.com/IPO", "purchaseOrder"); + DataType targetDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, new XMLType(root, null)); + // targetDataType.setMetadata(JAXBContextHelper.JAXB_CONTEXT_PATH, contextPath); + + TransformationContext tContext = createMock(TransformationContext.class); + expect(tContext.getTargetDataType()).andReturn(targetDataType).anyTimes(); + expect(tContext.getTargetOperation()).andReturn(null).anyTimes(); + replay(tContext); + + Object object1 = t0.transform(new StringReader(IPO_XML), tContext); + + DataType sourceDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, new XMLType(root, null)); + // sourceDataType.setMetadata(JAXBContextHelper.JAXB_CONTEXT_PATH, contextPath); + + TransformationContext tContext1 = createMock(TransformationContext.class); + expect(tContext1.getSourceDataType()).andReturn(sourceDataType).anyTimes(); + expect(tContext1.getTargetDataType()).andReturn(null).anyTimes(); + expect(tContext1.getSourceOperation()).andReturn(null).anyTimes(); + expect(tContext1.getTargetOperation()).andReturn(null).anyTimes(); + replay(tContext1); + + JAXB2Node t1 = new JAXB2Node(); + Node node = t1.transform(object1, tContext1); + + Assert.assertNotNull(node); + + Node2JAXB t2 = new Node2JAXB(); + Object object2 = t2.transform(node, tContext); + Assert.assertNotNull(object2); + + } + + public void testTransform3() throws Exception { + + DataType sourceDataType = new DataTypeImpl<Class>(PurchaseOrderType.class, null); + + TransformationContext tContext1 = createMock(TransformationContext.class); + expect(tContext1.getSourceDataType()).andReturn(sourceDataType).anyTimes(); + expect(tContext1.getTargetDataType()).andReturn(null).anyTimes(); + expect(tContext1.getSourceOperation()).andReturn(null).anyTimes(); + expect(tContext1.getTargetOperation()).andReturn(null).anyTimes(); + replay(tContext1); + + JAXB2Node t1 = new JAXB2Node(); + PurchaseOrderType po = new ObjectFactory().createPurchaseOrderType(); + Node node = t1.transform(po, tContext1); + + Assert.assertNotNull(node); + + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandlerTestCase.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandlerTestCase.java new file mode 100644 index 0000000000..c10a5227ce --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandlerTestCase.java @@ -0,0 +1,90 @@ +/* + * 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.databinding.jaxb; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; +import org.apache.tuscany.sca.databinding.jaxb.JAXBWrapperHandler; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import com.example.stock.StockQuoteOffer; + +/** + * Test case for JAXBExceptionHandler + * + * @version $Rev$ $Date$ + */ +public class JAXBWrapperHandlerTestCase extends TestCase { + private static final QName ELEMENT = new QName("http://www.example.com/stock", "stockQuoteOffer"); + private static final QName INPUT = new QName("", "input"); + private JAXBWrapperHandler handler; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + this.handler = new JAXBWrapperHandler(); + } + + public void testCreate() { + ElementInfo element = new ElementInfo(ELEMENT, null); + Operation op = new OperationImpl(); + WrapperInfo wrapperInfo = new WrapperInfo(JAXBDataBinding.NAME, element, null, null, null); + wrapperInfo.setInputWrapperType(new DataTypeImpl<XMLType>(JAXBDataBinding.NAME, StockQuoteOffer.class, + XMLType.UNKNOWN)); + op.setWrapper(wrapperInfo); + Object offer = handler.create(op, true); + Assert.assertTrue(offer instanceof StockQuoteOffer); + } + + public void testSetChild() { + StockQuoteOffer wrapper = new StockQuoteOffer(); + handler.setChild(wrapper, 0, new ElementInfo(INPUT, null), "IBM"); + Assert.assertEquals("IBM", wrapper.getInput()); + } + + public void testGetChildren() { + StockQuoteOffer wrapper = new StockQuoteOffer(); + wrapper.setInput("IBM"); + List<ElementInfo> elements = new ArrayList<ElementInfo>(); + elements.add(new ElementInfo(INPUT, null)); + WrapperInfo wrapperInfo = new WrapperInfo(JAXBDataBinding.NAME, null, null, elements, null); + Operation op = new OperationImpl(); + op.setWrapper(wrapperInfo); + List children = handler.getChildren(wrapper, op, true); + assertNotNull(children); + assertEquals(1, children.size()); + assertEquals("IBM", children.get(0)); + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyBean.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyBean.java new file mode 100644 index 0000000000..9bdfb108fe --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyBean.java @@ -0,0 +1,162 @@ +/* + * 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.databinding.jaxb; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + * @version $Rev$ $Date$ + */ +public class MyBean { + private int age; + private String name; + private float[] rates = new float[] {1.0f, 2.0f}; + private List<String> notes = new ArrayList<String>(); + private Map<String, Integer> map = new HashMap<String, Integer>(); + private Object service; + private Object otherService; + private boolean good; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<String> getNotes() { + return notes; + } + + public void setNotes(List<String> notes) { + this.notes = notes; + } + + public float[] getRates() { + return rates; + } + + public void setRates(float[] rates) { + this.rates = rates; + } + + public Map<String, Integer> getMap() { + return map; + } + + public void setMap(Map<String, Integer> map) { + this.map = map; + } + + public Object getService() { + return service; + } + + public void setService(Object service) { + this.service = service; + } + + public Object getOtherService() { + return otherService; + } + + public void setOtherService(Object otherService) { + this.otherService = otherService; + } + + public boolean isGood() { + return good; + } + + public void setGood(boolean good) { + this.good = good; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + age; + result = prime * result + (good ? 1231 : 1237); + result = prime * result + ((map == null) ? 0 : map.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((notes == null) ? 0 : notes.hashCode()); + result = prime * result + ((otherService == null) ? 0 : otherService.hashCode()); + result = prime * result + Arrays.hashCode(rates); + result = prime * result + ((service == null) ? 0 : service.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final MyBean other = (MyBean)obj; + if (age != other.age) + return false; + if (good != other.good) + return false; + if (map == null) { + if (other.map != null) + return false; + } else if (!map.equals(other.map)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (notes == null) { + if (other.notes != null) + return false; + } else if (!notes.equals(other.notes)) + return false; + if (otherService == null) { + if (other.otherService != null) + return false; + } else if (!otherService.equals(other.otherService)) + return false; + if (!Arrays.equals(rates, other.rates)) + return false; + if (service == null) { + if (other.service != null) + return false; + } else if (!service.equals(other.service)) + return false; + return true; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyInterface.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyInterface.java new file mode 100644 index 0000000000..b8e9ee7f7d --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyInterface.java @@ -0,0 +1,29 @@ +/* + * 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.databinding.jaxb; + +/** + * @version $Rev$ $Date$ + */ +public interface MyInterface { + void setId(String id); + + String getId(); +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyInterfaceImpl.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyInterfaceImpl.java new file mode 100644 index 0000000000..5c511e6ccb --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MyInterfaceImpl.java @@ -0,0 +1,67 @@ +/* + * 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.databinding.jaxb; + +/** + * @version $Rev$ $Date$ + */ +public class MyInterfaceImpl implements MyInterface { + private String id; + + /** + * @see org.apache.tuscany.databinding.jaxb.MyInterface#getId() + */ + public String getId() { + return id; + } + + /** + * @see org.apache.tuscany.databinding.jaxb.MyInterface#setId(java.lang.String) + */ + public void setId(String id) { + this.id = id; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final MyInterfaceImpl other = (MyInterfaceImpl)obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MySubBean.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MySubBean.java new file mode 100644 index 0000000000..62dfa6f73c --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/MySubBean.java @@ -0,0 +1,35 @@ +/* + * 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.databinding.jaxb; + +/** + * @version $Rev$ $Date$ + */ +public class MySubBean extends MyBean { + private String addtional; + + public String getAddtional() { + return addtional; + } + + public void setAddtional(String addtional) { + this.addtional = addtional; + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/POJOTestCase.java b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/POJOTestCase.java new file mode 100644 index 0000000000..0a3d64a705 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/java/org/apache/tuscany/sca/databinding/jaxb/POJOTestCase.java @@ -0,0 +1,250 @@ +/* + * 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.databinding.jaxb; + +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Collections; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.stream.StreamSource; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.databinding.jaxb.JAXB2XMLStreamReader; + +import com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader; +import com.sun.xml.bind.v2.model.core.Ref; +import com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder; +import com.sun.xml.bind.v2.model.runtime.RuntimeClassInfo; +import com.sun.xml.bind.v2.model.runtime.RuntimePropertyInfo; +import com.sun.xml.bind.v2.model.runtime.RuntimeTypeInfoSet; +import com.sun.xml.bind.v2.runtime.IllegalAnnotationsException; +import com.sun.xml.bind.v2.runtime.JAXBContextImpl; + +/** + * + * @version $Rev$ $Date$ + */ +public class POJOTestCase extends TestCase { + public void testPOJO() throws Exception { + JAXBContext context = JAXBContext.newInstance(MyBean.class, MyInterfaceImpl.class); + StringWriter writer = new StringWriter(); + MyBean bean = new MyBean(); + bean.setName("Test"); + bean.setAge(20); + bean.getNotes().add("1"); + bean.getNotes().add("2"); + bean.getMap().put("1", 1); + MyInterface service = new MyInterfaceImpl(); + service.setId("ID001"); + bean.setService(service); + bean.setOtherService(service); + JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, bean); + context.createMarshaller().marshal(element, writer); + // System.out.println(writer.toString()); + + Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString())); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertTrue(e2.getValue() instanceof MyBean); + MyBean newBean = (MyBean)e2.getValue(); + assertEquals(bean, newBean); + } + + public void testPOJOArray() throws Exception { + JAXBContext context = JAXBContext.newInstance(MyBean[].class); + StringWriter writer = new StringWriter(); + MySubBean bean = new MySubBean(); + bean.setAddtional("SUB"); + bean.setName("Test"); + bean.setAge(20); + bean.getNotes().add("1"); + bean.getNotes().add("2"); + bean.getMap().put("1", 1); + + JAXBElement<Object> element = + new JAXBElement<Object>(new QName("http://ns1", "beans"), Object.class, new MyBean[] {bean}); + context.createMarshaller().marshal(element, writer); + System.out.println(writer.toString()); + + Object result = + context.createUnmarshaller().unmarshal(new StreamSource(new StringReader(writer.toString())), + MyBean[].class); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertTrue(e2.getValue() instanceof MyBean[]); + MyBean newBean = ((MyBean[])e2.getValue())[0]; + assertFalse(newBean instanceof MySubBean); + } + + public void testXMLStreamReader() throws Exception { + JAXBContext context = JAXBContext.newInstance(MyBean.class, MyInterfaceImpl.class); + + MyBean bean = new MyBean(); + bean.setName("Test"); + bean.setAge(20); + bean.getNotes().add("1"); + bean.getNotes().add("2"); + bean.getMap().put("1", 1); + MyInterface service = new MyInterfaceImpl(); + service.setId("ID001"); + bean.setService(service); + bean.setOtherService(service); + QName name = new QName("http://ns1", "bean"); + JAXBElement<Object> element = new JAXBElement<Object>(name, Object.class, bean); + TransformationContext tContext = new TransformationContextImpl(); + XMLStreamReader reader = new JAXB2XMLStreamReader().transform(element, tContext); + +// XMLStreamReader2String t2 = new XMLStreamReader2String(); +// String xml = t2.transform(reader, null); + // System.out.println(xml); + Object result = context.createUnmarshaller().unmarshal(reader, MyBean.class); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertTrue(e2.getValue() instanceof MyBean); + MyBean newBean = (MyBean)e2.getValue(); + // FIXME :To be implemented + // assertEquals(bean, newBean); + } + + public void testString() throws Exception { + JAXBContext context = JAXBContext.newInstance(String.class); + StringWriter writer = new StringWriter(); + JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, "ABC"); + context.createMarshaller().marshal(element, writer); + // System.out.println(writer.toString()); + + Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString())); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertEquals("ABC", e2.getValue()); + } + + public void testNull() throws Exception { + JAXBContext context = JAXBContext.newInstance(String.class); + StringWriter writer = new StringWriter(); + JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, null); + element.setNil(true); + context.createMarshaller().marshal(element, writer); + // System.out.println(writer.toString()); + StreamSource source = new StreamSource(new StringReader(writer.toString())); + Object result = context.createUnmarshaller().unmarshal(source, String.class); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertNull(e2.getValue()); + } + + public void testArray() throws Exception { + JAXBContext context = JAXBContext.newInstance(String[].class); + StringWriter writer = new StringWriter(); + JAXBElement<Object> element = + new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, new String[] {"ABC", "123"}); + context.createMarshaller().marshal(element, writer); + // System.out.println(writer.toString()); + + Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString())); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertTrue(e2.getValue() instanceof String[]); + } + + public void testByteArray() throws Exception { + JAXBContext context = JAXBContext.newInstance(byte[].class); + StringWriter writer = new StringWriter(); + JAXBElement<Object> element = + new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, "ABC".getBytes()); + context.createMarshaller().marshal(element, writer); + String xml = writer.toString(); + assertTrue(xml.contains("QUJD")); + assertTrue(xml.contains("base64Binary")); + + Object result = context.createUnmarshaller().unmarshal(new StringReader(xml)); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertTrue(e2.getValue() instanceof byte[]); + } + + public void testPrimitive() throws Exception { + JAXBContext context = JAXBContext.newInstance(int.class); + StringWriter writer = new StringWriter(); + JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, 1); + context.createMarshaller().marshal(element, writer); + // System.out.println(writer.toString()); + + Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString())); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertEquals(1, e2.getValue()); + } + + /* + public void testException() throws Exception { + JAXBContext context = JAXBContext.newInstance(IllegalArgumentException.class); + StringWriter writer = new StringWriter(); + Exception e = new IllegalArgumentException("123"); + JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, e); + context.createMarshaller().marshal(element, writer); + System.out.println(writer.toString()); + + Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString())); + assertTrue(result instanceof JAXBElement); + JAXBElement e2 = (JAXBElement)result; + assertTrue(e2.getValue() instanceof Exception); + } + */ + + private static RuntimeTypeInfoSet create(Class... classes) throws Exception { + IllegalAnnotationsException.Builder errorListener = new IllegalAnnotationsException.Builder(); + RuntimeInlineAnnotationReader reader = new RuntimeInlineAnnotationReader(); + JAXBContextImpl context = + new JAXBContextImpl(classes, null, Collections.<Class, Class> emptyMap(), null, false, reader, false, false); + RuntimeModelBuilder builder = + new RuntimeModelBuilder(context, reader, Collections.<Class, Class> emptyMap(), null); + builder.setErrorHandler(errorListener); + for (Class c : classes) + builder.getTypeInfo(new Ref<Type, Class>(c)); + + RuntimeTypeInfoSet r = builder.link(); + errorListener.check(); + return r; + } + + public void testReflection() throws Exception { + MyBean bean = new MyBean(); + RuntimeTypeInfoSet model = create(MyBean.class); + RuntimeClassInfo clsInfo = (RuntimeClassInfo)model.getTypeInfo(MyBean.class); + for (RuntimePropertyInfo p : clsInfo.getProperties()) { + // System.out.print(p.getName()); + // System.out.println(" " + p.isCollection()); + if (p.getName().equals("notes")) { + Collection c = (Collection)p.getAccessor().get(bean); + c.add("123"); + } + } + + } +} diff --git a/branches/sca-android/modules/databinding-jaxb/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-jaxb/src/test/resources/ipo.xsd new file mode 100755 index 0000000000..241ec15d36 --- /dev/null +++ b/branches/sca-android/modules/databinding-jaxb/src/test/resources/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-job/LICENSE b/branches/sca-android/modules/databinding-job/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/branches/sca-android/modules/databinding-job/NOTICE b/branches/sca-android/modules/databinding-job/NOTICE new file mode 100644 index 0000000000..94481d6cfa --- /dev/null +++ b/branches/sca-android/modules/databinding-job/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-job/pom.xml b/branches/sca-android/modules/databinding-job/pom.xml new file mode 100644 index 0000000000..fa16671342 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/pom.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-job</artifactId> + <name>Apache Tuscany SCA Data Binding for XML Jobs</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding-axiom</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>javax.xml.stream</groupId> + <artifactId>stax-api</artifactId> + <version>1.0-2</version> + </dependency> + + <dependency> + <groupId>com.thoughtworks.xstream</groupId> + <artifactId>xstream</artifactId> + <version>1.2.2</version> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-api</artifactId> + <exclusions> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + </exclusions> + <version>1.2.5</version> + </dependency> + + <dependency> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + <version>2.8.1</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-impl</artifactId> + <version>1.2.5</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>wstx-asl</artifactId> + <version>3.2.1</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.job</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.job*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/Job.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/Job.java new file mode 100644 index 0000000000..98ca6c7429 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/Job.java @@ -0,0 +1,32 @@ +/* + * 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.databinding.job; + +public interface Job<T, E> { + public T compute(E v); + + public boolean eos(); + + public int getType(); + + public static int NULL_JOB = 0; + public static int REGULAR_JOB = 1; + public static int RESULT_JOB = 2; + // public boolean reusable(); +} diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/Job2OMElement.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/Job2OMElement.java new file mode 100644 index 0000000000..9752815640 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/Job2OMElement.java @@ -0,0 +1,84 @@ +/* + * 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.databinding.job; + +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.ObjectOutputStream; + +import javax.activation.DataHandler; +import javax.xml.namespace.QName; + +import org.apache.axiom.attachments.ByteArrayDataSource; +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.axiom.om.OMText; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter.Base64Binary; +import org.apache.tuscany.sca.databinding.axiom.AxiomHelper; + +@SuppressWarnings("unchecked") +public class Job2OMElement extends BaseTransformer<Job, OMElement> implements + PullTransformer<Job, OMElement> { + + @Override + protected Class getSourceType() { + return Job.class; + } + + @Override + protected Class getTargetType() { + return OMElement.class; + } + + public OMElement transform(Job source, TransformationContext context) { + OMElement element = null; + + try { + // JobDataSource dataSource = new JobDataSource(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + out.writeObject(source); + out.close(); + byte[] bytes = bos.toByteArray(); + // ByteArrayDataSource ds = new ByteArrayDataSource(bytes); + OMFactory factory = OMAbstractFactory.getOMFactory(); + OMNamespace ns = AxiomHelper.createOMNamespace(factory, new QName( + "http://job")); + element = factory.createOMElement("jobreference", ns); + // OMText data = factory.createOMText(new DataHandler(ds), true); + // element.addChild(data); + element.setText(Base64Binary.encode(bytes)); + return element; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataBinding.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataBinding.java new file mode 100644 index 0000000000..0acea89ebf --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataBinding.java @@ -0,0 +1,36 @@ +/* + * 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.databinding.job; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; + +/** + * DataBinding for Jobs + */ +public class JobDataBinding extends BaseDataBinding { + + public static final String NAME = Job.class.getName(); + public static final String[] ALIASES = new String[] {"job"}; + + public JobDataBinding() { + super(NAME, ALIASES, Job.class); + } + +} diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataMap.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataMap.java new file mode 100644 index 0000000000..40ee2ff010 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataMap.java @@ -0,0 +1,70 @@ +/* + * 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.databinding.job; + +import java.util.HashMap; + +public class JobDataMap implements java.io.Serializable { + private static final long serialVersionUID = -2602843967597362950L; + private HashMap<String, Object> data = new HashMap<String, Object>(); + + public JobDataMap() { + super(); + } + + public <T> void addJobData(String name, T t) { + data.put(name, t); + } + + public Object getJobDataObject(String name) { + if (data.containsKey(name)) { + return data.get(name); + } + return null; + } + + public Class<?> getJobDataClass(String name) { + if (data.containsKey(name)) { + return data.get(name).getClass(); + } + return null; + } + + public Class<?>[] getJobDataClasses() { + int siz = data.keySet().size(); + int i = 0; + Class<?>[] claz = new Class<?>[siz]; + for (Object e : data.values()) { + claz[i] = e.getClass(); + ++i; + } + return claz; + } + + public Object[] getJobDataObjects() { + int siz = data.keySet().size(); + Object[] objs = new Object[siz]; + int i = 0; + for (Object e : data.values()) { + objs[i] = e.getClass(); + ++i; + } + return objs; + } +} diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataSource.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataSource.java new file mode 100644 index 0000000000..623be7e2b5 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobDataSource.java @@ -0,0 +1,53 @@ +/* + * 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.databinding.job; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class JobDataSource implements javax.activation.DataSource { + private ByteArrayOutputStream os; + + public JobDataSource() { + os = new ByteArrayOutputStream(); + } + + public String getContentType() { + return "application/octet-stream"; + } + + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(os.toByteArray()); + } + + public String getName() { + return "jobreference"; + } + + public byte[] getBytes() { + return os.toByteArray(); + } + + public OutputStream getOutputStream() throws IOException { + return os; + } +}
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobExecutionContext.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobExecutionContext.java new file mode 100644 index 0000000000..8c98fd2e26 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/JobExecutionContext.java @@ -0,0 +1,45 @@ +/* + * 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.databinding.job; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver; + +public class JobExecutionContext implements java.io.Serializable { + private JobDataMap jobData; + + public JobDataMap getJobData() { + return jobData; + } + + public void storeJSONData(String jsonData) { + XStream xstream = new XStream(new JsonHierarchicalStreamDriver()); + jobData = (JobDataMap) xstream.fromXML(jsonData); + } + + public String getJSONData() { + XStream xstream = new XStream(new JsonHierarchicalStreamDriver()); + String jsonData = xstream.toXML(jobData); + return jsonData; + } + + public void setJobData(JobDataMap jdm) { + this.jobData = jdm; + } +} diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/OMElement2Job.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/OMElement2Job.java new file mode 100644 index 0000000000..057da6b67f --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/OMElement2Job.java @@ -0,0 +1,73 @@ +/* + * 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.databinding.job; + +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter.Base64Binary; + +/** + * Transformer to convert data from an OMElement to Job + */ +@SuppressWarnings("unchecked") +public class OMElement2Job extends BaseTransformer<OMElement, Job> implements + PullTransformer<OMElement, Job> { + + public Job transform(OMElement source, TransformationContext context) { + try { + + // OMText binaryNode = (OMText) source.getFirstOMChild(); + // DataHandler actualDH = (DataHandler) binaryNode.getDataHandler(); + // ByteArrayDataSource ds = + // (ByteArrayDataSource)actualDH.getDataSource(); + String value = (String) source.getText(); + ByteArrayInputStream bis = new ByteArrayInputStream(Base64Binary + .decode(value)); + ObjectInputStream ois = new ObjectInputStream(bis); + Object obj = ois.readObject(); + ois.close(); + Job aReference = (Job) obj; + return aReference; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class getSourceType() { + return OMElement.class; + } + + @Override + public Class getTargetType() { + return Job.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/RemoteJob.java b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/RemoteJob.java new file mode 100644 index 0000000000..693e0f1af7 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/java/org/apache/tuscany/sca/databinding/job/RemoteJob.java @@ -0,0 +1,35 @@ +/* + * 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.databinding.job; + +/** + * This an abstract class to represent a Job with a Context + * + */ +public abstract class RemoteJob<T> implements Job<T, JobExecutionContext>, + java.io.Serializable { + protected JobExecutionContext context = new JobExecutionContext(); + + public abstract T compute(JobExecutionContext v); + + public JobExecutionContext getContext() { + return context; + } + +} diff --git a/branches/sca-android/modules/databinding-job/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-job/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..7fb334e529 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,20 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.job.JobDataBinding;type=org.apache.tuscany.sca.databinding.job.Job,name=job + diff --git a/branches/sca-android/modules/databinding-job/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-job/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..f42a526a48 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,18 @@ +# 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. +org.apache.tuscany.sca.databinding.job.Job2OMElement;source=org.apache.tuscany.sca.databinding.job.Job,target=org.apache.axiom.om.OMElement,weight=10 +org.apache.tuscany.sca.databinding.job.OMElement2Job;source=org.apache.axiom.om.OMElement,target=org.apache.tuscany.sca.databinding.job.Job,weight=10 diff --git a/branches/sca-android/modules/databinding-job/src/test/resources/ipo.xml b/branches/sca-android/modules/databinding-job/src/test/resources/ipo.xml new file mode 100644 index 0000000000..df901d183d --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/test/resources/ipo.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<ipo:purchaseOrder + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ipo="http://www.example.com/IPO" + xsi:schemaLocation="http://www.example.com/IPO ipo.xsd" + orderDate="1999-12-01"> + + <shipTo exportCode="1" xsi:type="ipo:UKAddress"> + <name>Helen Zoe</name> + <street>47 Eden Street</street> + <city>Cambridge</city> + <postcode>CB1 1JR</postcode> + </shipTo> + + <billTo xsi:type="ipo:USAddress"> + <name>Robert Smith</name> + <street>8 Oak Avenue</street> + <city>Old Town</city> + <state>PA</state> + <zip>95819</zip> + </billTo> + + <items> + <item partNum="833-AA"> + <productName>Lapis necklace</productName> + <quantity>1</quantity> + <USPrice>99.95</USPrice> + <ipo:comment>Want this for the holidays</ipo:comment> + <shipDate>1999-12-05</shipDate> + </item> + </items> +</ipo:purchaseOrder> + diff --git a/branches/sca-android/modules/databinding-job/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-job/src/test/resources/ipo.xsd new file mode 100644 index 0000000000..cce0cf1019 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/test/resources/ipo.xsd @@ -0,0 +1,155 @@ +<!--
+ * 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.
+-->
+
+<!--
+ * 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.
+-->
+<schema targetNamespace="http://www.example.com/IPO"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+
+ <annotation>
+ <documentation xml:lang="en">
+ International Purchase order schema for Example.com
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+
+ <element name="purchaseOrder" type="ipo:PurchaseOrderType" />
+
+ <element name="comment" type="string" />
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element name="shipTo" type="ipo:Address" />
+ <element name="billTo" type="ipo:Address" />
+ <element ref="ipo:comment" minOccurs="0" />
+ <element name="items" type="ipo:Items" />
+ </sequence>
+ <attribute name="orderDate" type="date" />
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string" />
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100" />
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal" />
+ <element ref="ipo:comment" minOccurs="0" />
+ <element name="shipDate" type="date"
+ minOccurs="0" />
+ </sequence>
+ <attribute name="partNum" type="ipo:SKU"
+ use="required" />
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}" />
+ </restriction>
+ </simpleType>
+
+ <complexType name="Address">
+ <sequence>
+ <element name="name" type="string" />
+ <element name="street" type="string" />
+ <element name="city" type="string" />
+ </sequence>
+ </complexType>
+
+ <complexType name="USAddress">
+ <complexContent>
+ <extension base="ipo:Address">
+ <sequence>
+ <element name="state" type="ipo:USState" />
+ <element name="zip" type="positiveInteger" />
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="UKAddress">
+ <complexContent>
+ <extension base="ipo:Address">
+ <sequence>
+ <element name="postcode" type="ipo:UKPostcode" />
+ </sequence>
+ <attribute name="exportCode" type="positiveInteger"
+ fixed="1" />
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <!-- other Address derivations for more countries -->
+
+ <simpleType name="USState">
+ <restriction base="string">
+ <enumeration value="AK" />
+ <enumeration value="AL" />
+ <enumeration value="AR" />
+ <enumeration value="CA" />
+ <enumeration value="PA" />
+ <!-- and so on ... -->
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Postcode">
+ <restriction base="string">
+ <length value="7" fixed="true" />
+ </restriction>
+ </simpleType>
+
+
+ <simpleType name="UKPostcode">
+ <restriction base="ipo:Postcode">
+ <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" />
+ </restriction>
+ </simpleType>
+
+
+
+</schema>
+
diff --git a/branches/sca-android/modules/databinding-job/src/test/resources/order.wsdl b/branches/sca-android/modules/databinding-job/src/test/resources/order.wsdl new file mode 100644 index 0000000000..913d9e4928 --- /dev/null +++ b/branches/sca-android/modules/databinding-job/src/test/resources/order.wsdl @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<definitions name="StockQuote" targetNamespace="http://example.com/order.wsdl" xmlns:tns="http://example.com/order.wsdl" + xmlns:xsd1="http://example.com/order.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://schemas.xmlsoap.org/wsdl/"> + + <types> + <schema targetNamespace="http://example.com/order.xsd" xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd"/> + <element name="checkOrderStatus"> + <complexType> + <sequence> + <element name="customerId" type="string" /> + <element name="order" type="ipo:PurchaseOrderType" /> + <element name="flag" type="int" /> + </sequence> + </complexType> + </element> + <element name="checkOrderStatusResponse"> + <complexType> + <sequence> + <element name="status" type="string" /> + </sequence> + </complexType> + </element> + <element name="note" type="string" /> + </schema> + </types> + + <message name="CheckOrderStatusInput1"> + <part name="body" element="xsd1:checkOrderStatus" /> + </message> + + <message name="CheckOrderStatusOutput1"> + <part name="body" element="xsd1:checkOrderStatusResponse" /> + </message> + + <message name="CheckOrderStatusInput2"> + <part name="p1" element="xsd1:checkOrderStatus" /> + <part name="p2" element="xsd1:note" /> + </message> + + <message name="CheckOrderStatusOutput2"> + <part name="p1" element="xsd1:checkOrderStatusResponse" /> + </message> + + <portType name="OrderPortType"> + <operation name="checkOrderStatus"> + <input message="tns:CheckOrderStatusInput1" /> + <output message="tns:CheckOrderStatusOutput1" /> + </operation> + <operation name="checkOrderStatus2"> + <input message="tns:CheckOrderStatusInput2" /> + <output message="tns:CheckOrderStatusOutput2" /> + </operation> + </portType> + +</definitions>
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-json/LICENSE b/branches/sca-android/modules/databinding-json/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/branches/sca-android/modules/databinding-json/NOTICE b/branches/sca-android/modules/databinding-json/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding-json/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-json/pom.xml b/branches/sca-android/modules/databinding-json/pom.xml new file mode 100644 index 0000000000..bc4a149b91 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/pom.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-json</artifactId> + <name>Apache Tuscany SCA Data Binding for JSON</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>com.metaparadigm</groupId> + <artifactId>json-rpc</artifactId> + <version>1.0</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.jettison</groupId> + <artifactId>jettison</artifactId> + <version>1.0.1</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-api</artifactId> + <version>1.2.5</version> + <exclusions> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + <exclusion> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + </exclusion> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-impl</artifactId> + <version>1.2.5</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.2</version> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + <exclusion> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.json</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.json*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2JavaBean.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2JavaBean.java new file mode 100644 index 0000000000..b1813c9eab --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2JavaBean.java @@ -0,0 +1,73 @@ +/* + * 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.databinding.json; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; + +import com.metaparadigm.jsonrpc.JSONSerializer; +import com.metaparadigm.jsonrpc.SerializerState; + +/** + * @version $Rev$ $Date$ + */ +public class JSON2JavaBean implements PullTransformer<Object, Object> { + private JSONSerializer serializer; + + public JSON2JavaBean() { + super(); + serializer = new JSONSerializer(); + try { + serializer.registerDefaultSerializers(); + } catch (Exception e) { + throw new TransformationException(e); + } + serializer.setMarshallClassHints(true); + serializer.setMarshallNullAttributes(true); + } + + public Object transform(Object source, TransformationContext context) { + if (source == null) { + return null; + } + + try { + SerializerState state = new SerializerState(); + return serializer.unmarshall(state, context.getTargetDataType().getPhysical(), source); + } catch (Exception e) { + throw new TransformationException(e); + } + + } + + public String getSourceDataBinding() { + return JSONDataBinding.NAME; + } + + public String getTargetDataBinding() { + return JavaBeansDataBinding.NAME; + } + + public int getWeight() { + return 5000; + } +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2String.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2String.java new file mode 100644 index 0000000000..4e08384f09 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2String.java @@ -0,0 +1,61 @@ +/* + * 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.databinding.json; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * @version $Rev$ $Date$ + */ +public class JSON2String extends BaseTransformer<Object, String> implements + PullTransformer<Object, String> { + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + public String transform(Object source, TransformationContext context) { + try { + return source.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 500; + } + + @Override + public String getSourceDataBinding() { + return JSONDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2XMLStreamReader.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2XMLStreamReader.java new file mode 100644 index 0000000000..b70f772696 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSON2XMLStreamReader.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.json; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader; +import org.codehaus.jettison.json.JSONObject; + +/** + * @version $Rev$ $Date$ + */ +public class JSON2XMLStreamReader extends BaseTransformer<Object, XMLStreamReader> implements + PullTransformer<Object, XMLStreamReader> { + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + public XMLStreamReader transform(Object source, TransformationContext context) { + try { + JSONObject json = JSONHelper.toJettison(source); + return new BadgerFishXMLStreamReader(json); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 500; + } + @Override + public String getSourceDataBinding() { + return JSONDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSONDataBinding.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSONDataBinding.java new file mode 100644 index 0000000000..4bda838b18 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSONDataBinding.java @@ -0,0 +1,75 @@ +/* + * 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.databinding.json; + + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.codehaus.jettison.json.JSONObject; + +/** + * JAXB DataBinding + * + * @version $Rev$ $Date$ + */ +public class JSONDataBinding extends BaseDataBinding { + public static final String NAME = "JSON"; + public static final String[] ALIASES = new String[] {"json"}; + + public static final String ROOT_NAMESPACE = "http://tuscany.apache.org/xmlns/sca/databinding/json/1.0"; + public static final QName ROOT_ELEMENT = new QName(ROOT_NAMESPACE, "root"); + + public JSONDataBinding() { + super(NAME, ALIASES, org.json.JSONObject.class); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + assert type != null; + Class cls = type.getPhysical(); + if (JSONObject.class.isAssignableFrom(cls) || org.json.JSONObject.class.isAssignableFrom(cls)) { + type.setDataBinding(getName()); + if (type.getLogical() == null) { + type.setLogical(XMLType.UNKNOWN); + } + return true; + } + return false; + } + + @SuppressWarnings("unchecked") + @Override + public Object copy(Object arg, DataType dataType, Operation operation) { + if (arg == null) { + return null; + } + try { + Class type = arg != null ? arg.getClass() : null; + return JSONHelper.toJSON(arg.toString(), type); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSONHelper.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSONHelper.java new file mode 100644 index 0000000000..fb29710506 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JSONHelper.java @@ -0,0 +1,91 @@ +/* + * 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.databinding.json; + +import java.text.ParseException; + +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + +/** + * @version $Rev$ $Date$ + */ +public class JSONHelper { + private JSONHelper() { + + } + + /** + * Convert to Jettison JSONObject + * @param source + * @return + */ + public static JSONObject toJettison(Object source) { + JSONObject json = null; + if (source instanceof JSONObject) { + json = (JSONObject)source; + } else if (source instanceof org.json.JSONObject) { + try { + json = new JSONObject(((org.json.JSONObject)source).toString()); + } catch (JSONException e) { + throw new IllegalArgumentException(e); + } + } + return json; + } + + /** + * Convert to org.json.JSONObject + * @param source + * @return + */ + public static org.json.JSONObject toJSONOrg(Object source) { + org.json.JSONObject json = null; + if (source instanceof JSONObject) { + try { + json = new org.json.JSONObject(((JSONObject)source).toString()); + } catch (ParseException e) { + throw new IllegalArgumentException(e); + } + } else if (source instanceof org.json.JSONObject) { + json = (org.json.JSONObject)source; + } + return json; + } + + public static <T> T toJSON(String json, Class<T> type) { + if (type == JSONObject.class) { + try { + return type.cast(new JSONObject(json)); + } catch (JSONException e) { + throw new IllegalArgumentException(e); + } + } else { + if (type == null) { + type = (Class<T>)org.json.JSONObject.class; + } + try { + return type.cast(new org.json.JSONObject(json)); + } catch (ParseException e) { + throw new IllegalArgumentException(e); + } + } + } +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSON.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSON.java new file mode 100644 index 0000000000..a928deef22 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSON.java @@ -0,0 +1,82 @@ +/* + * 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.databinding.json; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; + +import com.metaparadigm.jsonrpc.JSONSerializer; +import com.metaparadigm.jsonrpc.SerializerState; + +public class JavaBean2JSON extends BaseTransformer<Object, Object> implements PullTransformer<Object, Object> { + private JSONSerializer serializer; + + public JavaBean2JSON() { + serializer = new JSONSerializer(); + try { + serializer.registerDefaultSerializers(); + } catch (Exception e) { + throw new TransformationException(e); + } + serializer.setMarshallClassHints(true); + serializer.setMarshallNullAttributes(true); + } + + @Override + public String getSourceDataBinding() { + return JavaBeansDataBinding.NAME; + } + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + public String getTargetDataBinding() { + return JSONDataBinding.NAME; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + public Object toJSON(Object source) throws Exception { + if (source == null) { + return org.json.JSONObject.NULL; + } + + SerializerState state = new SerializerState(); + return serializer.marshall(state, source); + } + + public Object transform(Object source, TransformationContext context) { + try { + return toJSON(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSONObject.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSONObject.java new file mode 100644 index 0000000000..de023157bc --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSONObject.java @@ -0,0 +1,139 @@ +/* + * 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.databinding.json; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; + +public class JavaBean2JSONObject extends BaseTransformer<Object, Object> implements PullTransformer<Object, Object> { + private static final Comparator<PropertyDescriptor> COMPARATOR = new Comparator<PropertyDescriptor>() { + public int compare(PropertyDescriptor o1, PropertyDescriptor o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + private static final SimpleTypeMapperImpl MAPPER = new SimpleTypeMapperImpl(); + private static final Object[] NULL = null; + + private static String getStringValue(Object o) { + if (o == null) { + return null; + } + TypeInfo info = SimpleTypeMapperImpl.getXMLType(o.getClass()); + if (info != null) { + return MAPPER.toXMLLiteral(info.getQName(), o, null); + } else { + return String.valueOf(o); + } + } + + private static boolean isSimpleType(Class<?> javaType) { + return SimpleTypeMapperImpl.getXMLType(javaType) != null; + } + + public JavaBean2JSONObject() { + } + + @Override + public String getSourceDataBinding() { + return JavaBeansDataBinding.NAME; + } + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + public String getTargetDataBinding() { + return JSONDataBinding.NAME; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + public Object toJSON(Object source) throws Exception { + if (source == null) { + return JSONObject.NULL; + } + Class<?> type = source.getClass(); + if (isSimpleType(type)) { + return source; + } else if (type.isArray()) { + JSONArray array = new JSONArray(); + int i1 = Array.getLength(source); + for (int j = 0; j < i1; j++) { + Object o = Array.get(source, j); + array.put(toJSON(o)); + } + return array; + } else if (Collection.class.isAssignableFrom(type)) { + Collection c = (Collection)source; + JSONArray array = new JSONArray(); + for (Object element : c) { + array.put(toJSON(element)); + } + return array; + } + JSONObject json = new JSONObject(); + BeanInfo beanInfo = Introspector.getBeanInfo(type); + PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors(); + Collections.sort(Arrays.asList(propDescs), COMPARATOR); + + for (int i = 0; i < propDescs.length; i++) { + PropertyDescriptor propDesc = propDescs[i]; + Class<?> pType = propDesc.getPropertyType(); + if ("class".equals(propDesc.getName())) { + continue; + } + Object pValue = propDesc.getReadMethod().invoke(source, NULL); + json.put(propDesc.getName(), toJSON(pValue)); + } + return json; + + } + + public Object transform(Object source, TransformationContext context) { + try { + return toJSON(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/String2JSON.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/String2JSON.java new file mode 100644 index 0000000000..ff5968bccd --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/String2JSON.java @@ -0,0 +1,64 @@ +/* + * 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.databinding.json; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * @version $Rev$ $Date$ + */ +public class String2JSON extends BaseTransformer<String, Object> implements PullTransformer<String, Object> { + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + public Object transform(String source, TransformationContext context) { + try { + Class type = null; + if (context != null && context.getTargetDataType() != null) { + type = context.getTargetDataType().getPhysical(); + } + return JSONHelper.toJSON(source, type); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 500; + } + + @Override + public String getTargetDataBinding() { + return JSONDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/XMLStreamReader2JSON.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/XMLStreamReader2JSON.java new file mode 100644 index 0000000000..aa75afc9d4 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/XMLStreamReader2JSON.java @@ -0,0 +1,77 @@ +/* + * 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.databinding.json; + +import java.io.StringWriter; + +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.xml.XMLStreamSerializer; +import org.codehaus.jettison.badgerfish.BadgerFishXMLStreamWriter; + +/** + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2JSON extends BaseTransformer<XMLStreamReader, Object> implements + PullTransformer<XMLStreamReader, Object> { + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + public Object transform(XMLStreamReader source, TransformationContext context) { + try { + StringWriter writer = new StringWriter(); + XMLStreamWriter jsonWriter = new BadgerFishXMLStreamWriter(writer); + XMLStreamSerializer serializer = new XMLStreamSerializer(); + serializer.serialize(source, jsonWriter); + source.close(); + Class type = null; + if (context != null && context.getTargetDataType() != null) { + type = context.getTargetDataType().getPhysical(); + } + return JSONHelper.toJSON(writer.toString(), type); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 500; + } + + @Override + public String getTargetDataBinding() { + return JSONDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSON2OMElement.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSON2OMElement.java new file mode 100644 index 0000000000..1072b70029 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSON2OMElement.java @@ -0,0 +1,94 @@ +/* + * 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.databinding.json.axiom; + + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.Transformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.json.JSONDataBinding; +import org.apache.tuscany.sca.databinding.json.JSONHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.codehaus.jettison.json.JSONObject; +import org.osoa.sca.annotations.Service; + +/** + * @version $Rev$ $Date$ + */ +@Service(Transformer.class) +public class JSON2OMElement extends BaseTransformer<Object, OMElement> implements PullTransformer<Object, OMElement> { + + private OMFactory factory = OMAbstractFactory.getOMFactory(); + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<OMElement> getTargetType() { + return OMElement.class; + } + + public OMElement transform(Object source, TransformationContext context) { + try { + JSONObject json = JSONHelper.toJettison(source); + if (json == null) { + return null; + } + String ns = JSONDataBinding.ROOT_ELEMENT.getNamespaceURI(); + String name = JSONDataBinding.ROOT_ELEMENT.getLocalPart(); + if (context != null) { + DataType<?> dataType = context.getTargetDataType(); + Object logical = dataType.getLogical(); + if (logical instanceof XMLType) { + XMLType xmlType = (XMLType)logical; + if (xmlType.isElement()) { + ns = xmlType.getElementName().getNamespaceURI(); + name = xmlType.getElementName().getLocalPart(); + } + } + } + JSONBadgerfishDataSource ds = new JSONBadgerfishDataSource(json); + OMNamespace namespace = factory.createOMNamespace(ns, ""); + return factory.createOMElement(ds, name, namespace); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public int getWeight() { + return 500; + } + + @Override + public String getSourceDataBinding() { + return JSONDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSONBadgerfishDataSource.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSONBadgerfishDataSource.java new file mode 100644 index 0000000000..adc38772be --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSONBadgerfishDataSource.java @@ -0,0 +1,57 @@ +/* + * 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.databinding.json.axiom; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + +/** + * JSONDataSource keeps the JSON String inside and consumes it when needed. This is to be kept in the + * OMSourcedElementImpl and can be used either to expand the tree or get the JSON String directly without expanding. + * This uses the "Badgerfish" JSON convention. + * + * @version $Rev$ $Date$ + */ + +public class JSONBadgerfishDataSource extends JSONDataSource { + + public JSONBadgerfishDataSource(JSONObject json) { + super(json); + } + + /** + * Gives the StAX reader using the "Badgerfish" formatted input JSON String. + * + * @return The XMLStreamReader according to the JSON String. + * @throws javax.xml.stream.XMLStreamException if there is an error while making the StAX reader. + */ + @Override + public javax.xml.stream.XMLStreamReader getReader() throws XMLStreamException { + try { + return new BadgerFishXMLStreamReader(json); + } catch (JSONException e) { + throw new XMLStreamException(e); + } + + } +} diff --git a/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSONDataSource.java b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSONDataSource.java new file mode 100644 index 0000000000..5b0312056e --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/axiom/JSONDataSource.java @@ -0,0 +1,176 @@ +/* + * 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.databinding.json.axiom; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamReader; + +import org.apache.axiom.om.OMDataSource; +import org.apache.axiom.om.OMException; +import org.apache.axiom.om.OMOutputFormat; +import org.codehaus.jettison.json.JSONObject; +import org.codehaus.jettison.json.JSONTokener; +import org.codehaus.jettison.mapped.MappedXMLInputFactory; + +/** + * JSONDataSource keeps the JSON String inside and consumes it when needed. This is to be kept in the + * OMSourcedElementImpl and can be used either to expand the tree or get the JSON String directly without expanding. + * This uses the "Mapped" JSON convention. + * + * @version $Rev$ $Date$ + */ + +public class JSONDataSource implements OMDataSource { + protected JSONObject json; + + public JSONDataSource(JSONObject json) { + this.json = json; + } + + /** + * Writes JSON into the output stream. As this should write JSON, it directly gets the JSON string and writes it + * without expanding the tree. + * + * @param outputStream the stream to be written into + * @param omOutputFormat format of the message, this is ignored. + * @throws javax.xml.stream.XMLStreamException if there is an error while writing the message in to the output + * stream. + */ + public void serialize(OutputStream outputStream, OMOutputFormat omOutputFormat) + throws javax.xml.stream.XMLStreamException { + try { + String encoding = omOutputFormat == null ? "UTF-8" : omOutputFormat.getCharSetEncoding(); + outputStream.write(getJSONString().getBytes(encoding)); + } catch (IOException e) { + throw new OMException(); + } + } + + /** + * Writes JSON through the writer. As this should write JSON, it directly gets the JSON string and writes it without + * expanding the tree. + * + * @param writer Writer to be written into + * @param omOutputFormat format of the message, this is ignored. + * @throws javax.xml.stream.XMLStreamException if there is an error while writing the message through the writer. + */ + public void serialize(Writer writer, OMOutputFormat omOutputFormat) throws javax.xml.stream.XMLStreamException { + try { + writer.write(getJSONString()); + } catch (IOException e) { + throw new OMException(); + } + } + + /** + * Writes XML through the XMLStreamWriter. As the input data source is JSON, this method needs to get a StAX reader + * from that JSON String. Therefore this uses the getReader() method to get the StAX reader writes the events into + * the XMLStreamWriter. + * + * @param xmlStreamWriter StAX writer to be written into + * @throws javax.xml.stream.XMLStreamException if there is an error while writing the message through the StAX + * writer. + */ + public void serialize(javax.xml.stream.XMLStreamWriter xmlStreamWriter) throws javax.xml.stream.XMLStreamException { + XMLStreamReader reader = getReader(); + xmlStreamWriter.writeStartDocument(); + while (reader.hasNext()) { + int x = reader.next(); + switch (x) { + case XMLStreamConstants.START_ELEMENT: + xmlStreamWriter.writeStartElement(reader.getPrefix(), reader.getLocalName(), reader + .getNamespaceURI()); + int namespaceCount = reader.getNamespaceCount(); + for (int i = namespaceCount - 1; i >= 0; i--) { + xmlStreamWriter.writeNamespace(reader.getNamespacePrefix(i), reader.getNamespaceURI(i)); + } + int attributeCount = reader.getAttributeCount(); + for (int i = 0; i < attributeCount; i++) { + xmlStreamWriter.writeAttribute(reader.getAttributePrefix(i), + reader.getAttributeNamespace(i), + reader.getAttributeLocalName(i), + reader.getAttributeValue(i)); + } + break; + case XMLStreamConstants.START_DOCUMENT: + break; + case XMLStreamConstants.CHARACTERS: + xmlStreamWriter.writeCharacters(reader.getText()); + break; + case XMLStreamConstants.CDATA: + xmlStreamWriter.writeCData(reader.getText()); + break; + case XMLStreamConstants.END_ELEMENT: + xmlStreamWriter.writeEndElement(); + break; + case XMLStreamConstants.END_DOCUMENT: + xmlStreamWriter.writeEndDocument(); + break; + case XMLStreamConstants.SPACE: + break; + case XMLStreamConstants.COMMENT: + xmlStreamWriter.writeComment(reader.getText()); + break; + case XMLStreamConstants.DTD: + xmlStreamWriter.writeDTD(reader.getText()); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + xmlStreamWriter.writeProcessingInstruction(reader.getPITarget(), reader.getPIData()); + break; + case XMLStreamConstants.ENTITY_REFERENCE: + xmlStreamWriter.writeEntityRef(reader.getLocalName()); + break; + default: + throw new OMException(); + } + } + xmlStreamWriter.writeEndDocument(); + } + + /** + * Gives the StAX reader using the "Mapped" formatted input JSON String. + * + * @return The XMLStreamReader according to the JSON String. + * @throws javax.xml.stream.XMLStreamException if there is an error while making the StAX reader. + */ + + public javax.xml.stream.XMLStreamReader getReader() throws javax.xml.stream.XMLStreamException { + + Map<String, String> nsMap = new HashMap<String, String>(); + nsMap.put("", ""); + + // input factory for "Mapped" convention + MappedXMLInputFactory inputFactory = new MappedXMLInputFactory(nsMap); + String jsonString = this.getJSONString(); + return inputFactory.createXMLStreamReader(new JSONTokener(jsonString)); + } + + // returns the json string by consuming the JSON input stream. + protected String getJSONString() { + return json.toString(); + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-json/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..b0baaeb398 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,19 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.json.JSONDataBinding;type=JSON,name=json
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-json/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-json/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..b122533f6e --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,31 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.json.JSON2XMLStreamReader;source=JSON,target=javax.xml.stream.XMLStreamReader,weight=5000 +org.apache.tuscany.sca.databinding.json.XMLStreamReader2JSON;source=javax.xml.stream.XMLStreamReader,target=JSON,weight=5000,public=false +org.apache.tuscany.sca.databinding.json.JavaBean2JSON;source=java:complexType,target=JSON,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JavaBean2JSON;source=java:simpleType,target=JSON,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.axiom.JSON2OMElement;source=JSON,target=org.apache.axiom.om.OMElement,weight=500 +org.apache.tuscany.sca.databinding.json.JavaBean2JSON;source=java:array,target=JSON,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JavaBean2JSON;source=commonj.sdo.DataObject,target=JSON,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JavaBean2JSON;source=javax.xml.bind.JAXBElement,target=JSON,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JSON2JavaBean;source=JSON,target=java:complexType,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JSON2JavaBean;source=JSON,target=java:simpleType,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JSON2JavaBean;source=JSON,target=commonj.sdo.DataObject,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JSON2JavaBean;source=JSON,target=javax.xml.bind.JAXBElement,weight=80000,public=false +org.apache.tuscany.sca.databinding.json.JSON2JavaBean;source=JSON,target=java:array,weight=80000,public=false diff --git a/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/JSONTransformerTestCase.java b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/JSONTransformerTestCase.java new file mode 100644 index 0000000000..3c7f151ed7 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/JSONTransformerTestCase.java @@ -0,0 +1,128 @@ +/* + * 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.databinding.json; + +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.databinding.json.axiom.JSON2OMElement; +import org.apache.tuscany.sca.databinding.xml.XMLStreamSerializer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.json.JSONObject; + +public class JSONTransformerTestCase extends TestCase { + private static final String IPO_XML = "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + private static final String JSON_STR = "{\"xsl:root\":{\"@xmlns\":{\"xsl\":\"http://foo.com\"},\"data\":{\"$\":\"my json string\"}}}"; + + public void testXML2JSON() throws Exception { + XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(IPO_XML)); + XMLStreamReader2JSON t1 = new XMLStreamReader2JSON(); + JSONObject json = (JSONObject) t1.transform(reader, null); + Assert.assertNotNull(json); + + // Cannot round-trip as we hit a bug in Jettison: http://jira.codehaus.org/browse/JETTISON-37 + /* + JSON2XMLStreamReader t2 = new JSON2XMLStreamReader(); + XMLStreamReader reader2 = t2.transform(json, null); + StringWriter sw = new StringWriter(); + XMLStreamWriter streamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(sw); + new XMLStreamSerializer().serialize(reader2, streamWriter); + streamWriter.flush(); + System.out.println(sw.toString()); + */ + + } + + public void testJSON2XML() throws Exception { + JSON2XMLStreamReader t2 = new JSON2XMLStreamReader(); + XMLStreamReader reader2 = t2.transform(new JSONObject(JSON_STR), null); + StringWriter sw = new StringWriter(); + XMLStreamWriter streamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(sw); + new XMLStreamSerializer().serialize(reader2, streamWriter); + streamWriter.flush(); + Assert.assertTrue(sw.toString() + .contains("<xsl:root xmlns:xsl=\"http://foo.com\"><data>my json string</data></xsl:root>")); + } + + public void testJSON2OMElement() throws Exception { + JSON2OMElement t1 = new JSON2OMElement(); + TransformationContext context = new TransformationContextImpl(); + DataType dt = new DataTypeImpl(Object.class, new XMLType(new QName("http://foo.com", "root"), null)); + context.setTargetDataType(dt); + OMElement element = t1.transform(new JSONObject(JSON_STR), context); + StringWriter writer = new StringWriter(); + element.serialize(writer); + // System.out.println(writer.toString()); + } + + public void testString2JSON() throws Exception { + String json = "{\"name\":\"John\",\"age\":25}"; + String2JSON t1 = new String2JSON(); + JSONObject jsonObject = (JSONObject) t1.transform(json, null); + assertEquals(jsonObject.getString("name"), "John"); + assertEquals(jsonObject.getInt("age"), 25); + JSON2String t2 = new JSON2String(); + String str = t2.transform(jsonObject, null); + assertTrue(str.contains("\"name\":\"John\"")); + assertTrue(str.contains("\"age\":25")); + } +} diff --git a/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSONTestCase.java b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSONTestCase.java new file mode 100644 index 0000000000..3b36f5be74 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/JavaBean2JSONTestCase.java @@ -0,0 +1,170 @@ +/* + * 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.databinding.json; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.json.JSONObject; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class JavaBean2JSONTestCase { + + public static class MyBean { + private String name; + private int age; + private boolean vip; + private String friends[]; + private List<String> books; + private YourBean you; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public boolean isVip() { + return vip; + } + + public void setVip(boolean vip) { + this.vip = vip; + } + + public String[] getFriends() { + return friends; + } + + public void setFriends(String[] friends) { + this.friends = friends; + } + + public List<String> getBooks() { + return books; + } + + public void setBooks(List<String> books) { + this.books = books; + } + + public YourBean getYou() { + return you; + } + + public void setYou(YourBean you) { + this.you = you; + } + + } + + public static class YourBean { + private int id; + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Test + public void testBean2JSON() throws Exception { + MyBean me = new MyBean(); + me.setAge(30); + me.setBooks(new ArrayList<String>()); + me.setFriends(new String[] {"John", "Mike"}); + me.setVip(true); + me.setName("Me"); + YourBean you = new YourBean(); + you.setId(123); + you.setName(null); + me.setYou(you); + JavaBean2JSON t1 = new JavaBean2JSON(); + Object result = t1.transform(me, null); + System.out.println(result); + JSON2JavaBean t2 = new JSON2JavaBean(); + TransformationContext context = new TransformationContextImpl(); + context.setTargetDataType(new DataTypeImpl(MyBean.class, null)); + Object v = t2.transform(new JSONObject(result.toString()), context); + Assert.assertTrue(v instanceof MyBean); + // String json = + // "{\"age\":30,\"books\":[],\"friends\":[\"John\",\"Mike\"],\"name\":\"Me\",\"vip\":true,\"you\":{\"id\":123,\"name\":null}}"; + // Assert.assertEquals(json, result.toString()); + } + + @Test + public void testString2JSON() throws Exception { + JavaBean2JSONObject t1 = new JavaBean2JSONObject(); + Object result = t1.transform("ABC", null); + System.out.println(result); + JSON2JavaBean t2 = new JSON2JavaBean(); + TransformationContext context = new TransformationContextImpl(); + context.setTargetDataType(new DataTypeImpl(String.class, null)); + Object v = t2.transform(result, context); + Assert.assertTrue(v instanceof String); + Assert.assertEquals("ABC", v); + } + + @Test + public void testStringArray2JSON() throws Exception { + JavaBean2JSON t1 = new JavaBean2JSON(); + Object result = t1.transform(new String[] {"ABC", "DF"}, null); + System.out.println(result); + JSON2JavaBean t2 = new JSON2JavaBean(); + TransformationContext context = new TransformationContextImpl(); + context.setTargetDataType(new DataTypeImpl(String[].class, null)); + Object v = t2.transform(result, context); + Assert.assertTrue(v instanceof String[]); + String[] strs = (String[])v; + Assert.assertEquals("ABC", strs[0]); + Assert.assertEquals("DF", strs[1]); + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyBean.java b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyBean.java new file mode 100644 index 0000000000..60b293c1d4 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyBean.java @@ -0,0 +1,158 @@ +/* + * 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.databinding.json; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MyBean { + private int age; + private String name; + private float[] rates = new float[] {1.0f, 2.0f}; + private List<String> notes = new ArrayList<String>(); + private Map<String, Integer> map = new HashMap<String, Integer>(); + private Object service; + private Object otherService; + private boolean good; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<String> getNotes() { + return notes; + } + + public void setNotes(List<String> notes) { + this.notes = notes; + } + + public float[] getRates() { + return rates; + } + + public void setRates(float[] rates) { + this.rates = rates; + } + + public Map<String, Integer> getMap() { + return map; + } + + public void setMap(Map<String, Integer> map) { + this.map = map; + } + + public Object getService() { + return service; + } + + public void setService(Object service) { + this.service = service; + } + + public Object getOtherService() { + return otherService; + } + + public void setOtherService(Object otherService) { + this.otherService = otherService; + } + + public boolean isGood() { + return good; + } + + public void setGood(boolean good) { + this.good = good; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + age; + result = prime * result + (good ? 1231 : 1237); + result = prime * result + ((map == null) ? 0 : map.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((notes == null) ? 0 : notes.hashCode()); + result = prime * result + ((otherService == null) ? 0 : otherService.hashCode()); + result = prime * result + Arrays.hashCode(rates); + result = prime * result + ((service == null) ? 0 : service.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final MyBean other = (MyBean)obj; + if (age != other.age) + return false; + if (good != other.good) + return false; + if (map == null) { + if (other.map != null) + return false; + } else if (!map.equals(other.map)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (notes == null) { + if (other.notes != null) + return false; + } else if (!notes.equals(other.notes)) + return false; + if (otherService == null) { + if (other.otherService != null) + return false; + } else if (!otherService.equals(other.otherService)) + return false; + if (!Arrays.equals(rates, other.rates)) + return false; + if (service == null) { + if (other.service != null) + return false; + } else if (!service.equals(other.service)) + return false; + return true; + } +} diff --git a/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyInterface.java b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyInterface.java new file mode 100644 index 0000000000..d32e0763c7 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyInterface.java @@ -0,0 +1,29 @@ +/* + * 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.databinding.json; + +/** + * @version $Rev$ $Date$ + */ +public interface MyInterface { + void setId(String id); + + String getId(); +} diff --git a/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyInterfaceImpl.java b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyInterfaceImpl.java new file mode 100644 index 0000000000..3a2b95a4e2 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/MyInterfaceImpl.java @@ -0,0 +1,67 @@ +/* + * 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.databinding.json; + +/** + * @version $Rev$ $Date$ + */ +public class MyInterfaceImpl implements MyInterface { + private String id; + + /** + * @see org.apache.tuscany.databinding.jaxb.MyInterface#getId() + */ + public String getId() { + return id; + } + + /** + * @see org.apache.tuscany.databinding.jaxb.MyInterface#setId(java.lang.String) + */ + public void setId(String id) { + this.id = id; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final MyInterfaceImpl other = (MyInterfaceImpl)obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/POJOTestCase.java b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/POJOTestCase.java new file mode 100644 index 0000000000..84995baadf --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/POJOTestCase.java @@ -0,0 +1,87 @@ +/* + * 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.databinding.json; + +import java.lang.reflect.Array; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; + +public class POJOTestCase extends TestCase { + public void testPOJO() throws Exception { + MyBean bean = new MyBean(); + bean.setName("Test"); + bean.setAge(20); + bean.getNotes().add("1"); + bean.getNotes().add("2"); + bean.getMap().put("1", 1); + MyInterface service = new MyInterfaceImpl(); + service.setId("ID001"); + bean.setService(service); + bean.setOtherService(service); + + roundTrip(bean); + } + + private <T> void roundTrip(T bean) { + JavaBean2JSON t1 = new JavaBean2JSON(); + + Object json = t1.transform(bean, null); + System.out.println(json); + JSON2JavaBean t2 = new JSON2JavaBean(); + + TransformationContext context = new TransformationContextImpl(); + context.setTargetDataType(new DataTypeImpl(bean == null ? Object.class : bean.getClass(), null)); + Object newBean = t2.transform(json, context); + + if (newBean != null && newBean.getClass().isArray()) { + int len = Array.getLength(newBean); + assertEquals(Array.getLength(bean), len); + for (int i = 0; i < len; i++) { + assertEquals(Array.get(bean, i), Array.get(newBean, i)); + } + return; + } + assertEquals(bean, newBean); + } + + public void testString() throws Exception { + roundTrip("ABC"); + } + + public void testNull() throws Exception { + roundTrip(null); + } + + public void testArray() throws Exception { + roundTrip(new String[] {"123", "ABC"}); + } + + public void testByteArray() throws Exception { + roundTrip("ABC".getBytes()); + } + + public void testPrimitive() throws Exception { + roundTrip(123); + } + +} diff --git a/branches/sca-android/modules/databinding-json/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-json/src/test/resources/ipo.xsd new file mode 100644 index 0000000000..5a493e1746 --- /dev/null +++ b/branches/sca-android/modules/databinding-json/src/test/resources/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-saxon/LICENSE b/branches/sca-android/modules/databinding-saxon/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/branches/sca-android/modules/databinding-saxon/NOTICE b/branches/sca-android/modules/databinding-saxon/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-saxon/pom.xml b/branches/sca-android/modules/databinding-saxon/pom.xml new file mode 100644 index 0000000000..390bf1f4f5 --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/pom.xml @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-saxon</artifactId> + <name>Apache Tuscany SCA Data Binding for Saxon</name> + + <repositories> + <repository> + <snapshots> + <enabled>false</enabled> + </snapshots> + <id>rfeng</id> + <name>Tuscany Maven 2.0 Repository</name> + <url>http://svn.apache.org/repos/asf/incubator/tuscany/maven</url> + <layout>default</layout> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <!--dependency> + <groupId>net.sf.saxon</groupId> + <artifactId>saxon</artifactId> + <version>9.0.0.2</version> + </dependency> + + <dependency> + <groupId>net.sf.saxon</groupId> + <artifactId>saxon-api</artifactId> + <version>9.0.0.2</version> + </dependency> + + <dependency> + <groupId>net.sf.saxon</groupId> + <artifactId>saxon-dom</artifactId> + <version>9.0.0.2</version> + </dependency--> + + <dependency> + <groupId>net.sf.saxon</groupId> + <artifactId>saxon</artifactId> + <version>8.7</version> + </dependency> + + <dependency> + <groupId>net.sf.saxon</groupId> + <artifactId>saxon-dom</artifactId> + <version>8.7</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sdo</groupId> + <artifactId>tuscany-sdo-lib</artifactId> + <version>1.1.1</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sdo</groupId> + <artifactId>tuscany-sdo-impl</artifactId> + <version>1.1.1</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.1</version> + <scope>test</scope> + </dependency> + </dependencies> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.saxon</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.saxon*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/DataObject2NodeInfoTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/DataObject2NodeInfoTransformer.java new file mode 100644 index 0000000000..25f8ee886f --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/DataObject2NodeInfoTransformer.java @@ -0,0 +1,99 @@ +/* + * 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.databinding.saxon; + +import javax.xml.transform.dom.DOMResult; + +import net.sf.saxon.om.NodeInfo; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XMLHelper; + +/** + * Transforms SDO DataObject-s to NodeInfo objects needed by Saxon parser. + * + * For root element when Serializing the DataObject the name of its + * implemented interface is used with its first letter made lowercase. + * Also any namespaces that are defined are deleted, because otherwise + * the SaxonB parser does not work + * + * @version $Rev$ $Date$ + */ +public class DataObject2NodeInfoTransformer extends BaseTransformer<DataObject, NodeInfo> implements + PullTransformer<DataObject, NodeInfo> { + + private Node2NodeInfoTransformer node2NodeInfoTransformer; + + public DataObject2NodeInfoTransformer(Node2NodeInfoTransformer node2NodeInfoTransformer) { + this.node2NodeInfoTransformer = node2NodeInfoTransformer; + } + + public DataObject2NodeInfoTransformer() { + this.node2NodeInfoTransformer = new Node2NodeInfoTransformer(); + } + + public NodeInfo transform(DataObject source, TransformationContext context) { + // FIXME: Need to create the HelperContext from the transformation context + // FIXME: This is a big hack to create a document using the class name + XMLHelper helper = XMLHelper.INSTANCE; + String name = null; + if (source.getClass().getInterfaces().length > 0) { + name = source.getClass().getInterfaces()[0].getSimpleName(); + } else { + name = source.getClass().getName(); + } + + if (name.length() > 0) { + name = Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length()); + } + + try { + DOMResult domResult = new DOMResult(DOMHelper.newDocument()); + XMLDocument xmlDoc = helper.createDocument(source, null, name); + helper.save(xmlDoc, domResult, null); + return node2NodeInfoTransformer.transform(domResult.getNode(), context); + } catch (Exception e) { + throw new TransformationException(e); + } + + } + + @Override + protected Class<DataObject> getSourceType() { + return DataObject.class; + } + + @Override + protected Class<NodeInfo> getTargetType() { + return NodeInfo.class; + } + + @Override + public int getWeight() { + return 30 + node2NodeInfoTransformer.getWeight(); + } + +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/ItemList2ObjectTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/ItemList2ObjectTransformer.java new file mode 100644 index 0000000000..7122217b8b --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/ItemList2ObjectTransformer.java @@ -0,0 +1,153 @@ +/*
+ * 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.databinding.saxon;
+
+import java.lang.reflect.Array;
+
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.value.Value;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.saxon.collection.ItemList;
+
+/**
+ * Transforms each object contained in the ItemList object.
+ *
+ * If the object type is the same as the target type, it is not transformed.
+ *
+ * If the object is a NodeInfo, it's transformed to a DataObject.
+ *
+ * If the object is a Value, it's transformed to a Java object.
+ *
+ * If the target type is not an array, the first transformed object is returned.
+ *
+ * If the first transformed object type is not a target type, then a
+ * TransformException is thrown
+ *
+ * If the target type is an array, a array of this type is created containing
+ * all transformed objects and it is returned
+ *
+ * If any transformed object is not a target type, then a TransformException is
+ * thrown
+ *
+ * @version $Rev: 659284 $ $Date: 2008-05-22 14:26:18 -0800 (Thu, 22 May 2008) $
+ */
+public class ItemList2ObjectTransformer extends BaseTransformer<ItemList, Object> implements
+ PullTransformer<ItemList, Object> {
+
+ private NodeInfo2DataObjectTransformer nodeInfo2DataObjectTransformer = new NodeInfo2DataObjectTransformer();
+
+ public ItemList2ObjectTransformer() {
+ }
+
+ @Override
+ protected Class<ItemList> getSourceType() {
+ return ItemList.class;
+ }
+
+ @Override
+ protected Class<Object> getTargetType() {
+ return Object.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 30 + nodeInfo2DataObjectTransformer.getWeight();
+ }
+
+ public Object transform(ItemList source, TransformationContext context) {
+
+ if (source.size() == 0) {
+ return null;
+ }
+
+ Class<?> targetType = context.getTargetDataType().getPhysical();
+
+ if (targetType.isArray()) {
+ int i = 0;
+ Class<?> componentClass = targetType.getComponentType();
+ Object[] result = (Object[])Array.newInstance(componentClass, source.size());
+
+ try {
+
+ if (componentClass.isAssignableFrom(NodeInfo.class) || componentClass.isAssignableFrom(Value.class)) {
+
+ for (Item item : source) {
+ result[i++] = item;
+ }
+
+ } else {
+
+ for (Item item : source) {
+
+ if (item instanceof NodeInfo) {
+ result[i] = nodeInfo2DataObjectTransformer.transform((NodeInfo)item, context);
+
+ } else if (item instanceof Value) {
+ result[i] = Value.convert(item);
+
+ } else {
+ result[i] = item;
+ }
+
+ i++;
+
+ }
+
+ }
+
+ } catch (ArrayStoreException ex) {
+ throw new TransformationException(ex);
+
+ } catch (XPathException ex) {
+ throw new TransformationException(ex);
+ }
+
+ return result;
+
+ } else {
+ Item item = source.iterator().next();
+
+ if (item.getClass().isAssignableFrom(targetType)) {
+ return item;
+
+ } else if (item instanceof NodeInfo) {
+ return nodeInfo2DataObjectTransformer.transform((NodeInfo)item, context);
+
+ } else {
+
+ try {
+ return Value.convert(item);
+
+ } catch (XPathException e) {
+ throw new TransformationException(e);
+ }
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Node2NodeInfoTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Node2NodeInfoTransformer.java new file mode 100644 index 0000000000..fabadd34ea --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Node2NodeInfoTransformer.java @@ -0,0 +1,77 @@ +/* + * 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.databinding.saxon; + +import javax.xml.transform.dom.DOMSource; + +import net.sf.saxon.Configuration; +import net.sf.saxon.event.Builder; +import net.sf.saxon.om.NodeInfo; +import net.sf.saxon.trans.XPathException; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Node; + +/** + * Transforms DOM Node-s to NodeInfo objects needed by Saxon parser. + * + * Any namespaces that are defined are deleted, because otherwise + * the SaxonB parser does not work + * + * @version $Rev$ $Date$ + */ +public class Node2NodeInfoTransformer extends BaseTransformer<Node, NodeInfo> implements + PullTransformer<Node, NodeInfo> { + + public NodeInfo transform(Node source, TransformationContext context) { + Configuration configuration = SaxonDataBindingHelper.CURR_EXECUTING_CONFIG; + if (configuration == null) { + configuration = new Configuration(); + } + + NodeInfo docInfo = null; + try { + source = DOMHelper.promote(source); + docInfo = Builder.build(new DOMSource(source), null, configuration); + } catch (XPathException e) { + throw new TransformationException(e); + } + return docInfo; + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<NodeInfo> getTargetType() { + return NodeInfo.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2DataObjectTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2DataObjectTransformer.java new file mode 100644 index 0000000000..a5093f8cdf --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2DataObjectTransformer.java @@ -0,0 +1,91 @@ +/* + * 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.databinding.saxon; + +import java.io.IOException; + +import javax.xml.transform.dom.DOMSource; + +import net.sf.saxon.om.NodeInfo; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Document; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.XMLHelper; + +/** + * Transforms NodeInfo objects to SDO DataObjects. + * + * Before constructing the data object, resulting XML is populated + * with correct namespaces (which are taken from the logical target data type) + * These namespaces are crucial for constructing the right instance of + * the DataObject (i.e. if there is a SDO factory, an instance from this factory will + * be used, not the generic any data object) + * + * @version $Rev$ $Date$ + */ +public class NodeInfo2DataObjectTransformer extends BaseTransformer<NodeInfo, DataObject> implements + PullTransformer<NodeInfo, DataObject> { + + private NodeInfo2NodeTransformer nodeInfo2NodeTransformer; + + public NodeInfo2DataObjectTransformer(NodeInfo2NodeTransformer nodeInfo2NodeTransformer) { + this.nodeInfo2NodeTransformer = nodeInfo2NodeTransformer; + } + + public NodeInfo2DataObjectTransformer() { + this.nodeInfo2NodeTransformer = new NodeInfo2NodeTransformer(); + } + + @Override + protected Class<NodeInfo> getSourceType() { + return NodeInfo.class; + } + + @Override + protected Class<DataObject> getTargetType() { + return DataObject.class; + } + + @Override + public int getWeight() { + return 30 + nodeInfo2NodeTransformer.getWeight(); + } + + public DataObject transform(NodeInfo source, TransformationContext context) { + Document doc = (Document)nodeInfo2NodeTransformer.transform(source, context); + + return produceResult(doc); + } + + private DataObject produceResult(Document doc) { + try { + // FIXME: [rfeng] We should use the HelperContext from the context + DataObject resultingObject = + XMLHelper.INSTANCE.load(new DOMSource(doc), doc.getDocumentURI(), null).getRootObject(); + return resultingObject; + } catch (IOException e) { + throw new TransformationException(e); + } + } +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2JavaArrayTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2JavaArrayTransformer.java new file mode 100644 index 0000000000..36ebac3aea --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2JavaArrayTransformer.java @@ -0,0 +1,76 @@ +/*
+ * 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.databinding.saxon;
+
+import java.lang.reflect.Array;
+
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.value.Value;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.saxon.collection.ItemList;
+
+import commonj.sdo.DataObject;
+
+/**
+ * Transforms a NodeInfo object to a DataObject and return it in an array.
+ *
+ * @version $Rev: 659284 $ $Date: 2008-05-22 14:26:18 -0800 (Thu, 22 May 2008) $
+ */
+public class NodeInfo2JavaArrayTransformer extends
+ BaseTransformer<NodeInfo, Object[]> implements
+ PullTransformer<NodeInfo, Object[]> {
+
+ private NodeInfo2DataObjectTransformer nodeInfo2DataObjectTransformer = new NodeInfo2DataObjectTransformer();
+
+ public NodeInfo2JavaArrayTransformer() {}
+
+ @Override
+ protected Class<NodeInfo> getSourceType() {
+ return NodeInfo.class;
+ }
+
+ @Override
+ protected Class<Object[]> getTargetType() {
+ return Object[].class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 30 + nodeInfo2DataObjectTransformer.getWeight();
+ }
+
+ public Object[] transform(NodeInfo source, TransformationContext context) {
+ Object object = nodeInfo2DataObjectTransformer.transform(source, context);
+
+ Class<?> componentClass = context.getTargetDataType().getPhysical().getComponentType();
+ Object[] result = (Object[]) Array.newInstance(componentClass, 1);
+
+ result[0] = object;
+
+ return result;
+
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2NodeTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2NodeTransformer.java new file mode 100644 index 0000000000..1e5b816662 --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/NodeInfo2NodeTransformer.java @@ -0,0 +1,71 @@ +/* + * 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.databinding.saxon; + +import java.util.Properties; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.dom.DOMResult; + +import net.sf.saxon.om.NodeInfo; +import net.sf.saxon.query.QueryResult; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Transforms NodeInfo objects to SDO DataObjects. + * + * @version $Rev$ $Date$ + */ +public class NodeInfo2NodeTransformer extends BaseTransformer<NodeInfo, Node> implements + PullTransformer<NodeInfo, Node> { + + public Node transform(NodeInfo source, TransformationContext context) { + DOMResult destination = new DOMResult(); + try { + Properties props = new Properties(); + props.setProperty(OutputKeys.METHOD, "xml"); + props.setProperty(OutputKeys.INDENT, "yes"); + QueryResult.serialize(source, destination, props, source.getConfiguration()); + } catch (Exception e) { + throw new TransformationException(e); + } + return destination.getNode(); + } + + @Override + protected Class<NodeInfo> getSourceType() { + return NodeInfo.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Object2ValueTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Object2ValueTransformer.java new file mode 100644 index 0000000000..616bcca6c5 --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Object2ValueTransformer.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.saxon; + +import net.sf.saxon.value.FloatValue; +import net.sf.saxon.value.ObjectValue; +import net.sf.saxon.value.Value; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; + +/** + * Transforms generic java objects to Value objects needed by Saxon parser. + * + * @version $Rev$ $Date$ + */ +public class Object2ValueTransformer extends BaseTransformer<Object, Value> implements PullTransformer<Object, Value> { + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<Value> getTargetType() { + return Value.class; + } + + @Override + public String getSourceDataBinding() { + return JavaBeansDataBinding.NAME; + } + + @Override + public int getWeight() { + return 10000; + } + + public Value transform(Object source, TransformationContext context) { + // WORKAROUND for ClassCastException in ObjectValue.toJavaObject(float) + if (source instanceof Float) { + return new FloatValue(((Float)source).floatValue()); + } + return new ObjectValue(source); + } + +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonDataBindingHelper.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonDataBindingHelper.java new file mode 100644 index 0000000000..ecb20b24b5 --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonDataBindingHelper.java @@ -0,0 +1,41 @@ +/* + * 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.databinding.saxon; + +import net.sf.saxon.Configuration; + +/** + * Provides helper functionality for Saxon data bindings + * @version $Rev$ $Date$ + */ +public class SaxonDataBindingHelper { + /** + * This variable is meaningful only in the context of XQoery expression + * execution. It is used by the DataObject2NodeInfoTransformer and + * Node2NodeInfoTransformer to create the correct NodeInfo objects + * in the Output2Output transformations. + * For Input2Input transformations it is meaningless: + * - if it is null - it is ignored by the transformers as they create new + * configuration objects + * - if it is not null - it is reused + * However the XQueryInvoker transforms all NodeInfo-s to NodeInfo-s with + * its current configuration, so there is no effect for Input2Input transformations + */ + public static Configuration CURR_EXECUTING_CONFIG = null; +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonNodeDataBinding.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonNodeDataBinding.java new file mode 100644 index 0000000000..ccf842710d --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonNodeDataBinding.java @@ -0,0 +1,54 @@ +/* + * 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.databinding.saxon; + + +import net.sf.saxon.om.NodeInfo; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * Represents data binding for parameters of type NodeInfo. + * + * The NodeInfo type is the type accepted by the Saxon XQuery processor for + * all XML - based content (i.e. not strings and simple types) + * + * @version $Rev$ $Date$ + */ +public class SaxonNodeDataBinding extends BaseDataBinding { + + public static final String NAME = NodeInfo.class.getName(); + public static final String[] ALIASES = new String[] {"saxon_node"}; + + public SaxonNodeDataBinding() { + super(NAME, NodeInfo.class); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (super.introspect(type, operation)) { + // type.setLogical(XMLType.UNKNOWN); + return true; + } else { + return false; + } + } +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonValueDataBinding.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonValueDataBinding.java new file mode 100644 index 0000000000..2f51cf86ec --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SaxonValueDataBinding.java @@ -0,0 +1,53 @@ +/* + * 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.databinding.saxon; + + +import net.sf.saxon.value.Value; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * Represents data binding for parameters of type Value. + * + * The Value type is the type accepted by the Saxon XQuery processor for + * all simple types and strings + * + * @version $Rev$ $Date$ + */ +public class SaxonValueDataBinding extends BaseDataBinding { + public static final String NAME = Value.class.getName(); + public static final String[] ALIASES = new String[] {"saxon_value"}; + + public SaxonValueDataBinding() { + super(NAME, Value.class); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (super.introspect(type, operation)) { + // type.setLogical(XMLType.UNKNOWN); + return true; + } else { + return false; + } + } +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SimpleType2ValueTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SimpleType2ValueTransformer.java new file mode 100644 index 0000000000..67d89a6e0b --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/SimpleType2ValueTransformer.java @@ -0,0 +1,87 @@ +/* + * 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.databinding.saxon; + +import java.math.BigDecimal; + +import net.sf.saxon.value.DecimalValue; +import net.sf.saxon.value.DoubleValue; +import net.sf.saxon.value.FloatValue; +import net.sf.saxon.value.IntegerValue; +import net.sf.saxon.value.ObjectValue; +import net.sf.saxon.value.StringValue; +import net.sf.saxon.value.Value; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; + +/** + * Transforms simple types and strings to Value objects needed by Saxon parser + * @version $Rev$ $Date$ + */ +public class SimpleType2ValueTransformer extends BaseTransformer<Object, Value> implements + PullTransformer<Object, Value> { + + @Override + public String getSourceDataBinding() { + return SimpleJavaDataBinding.NAME; + } + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<Value> getTargetType() { + return Value.class; + } + + @Override + public int getWeight() { + return 10000; + } + + public Value transform(Object source, TransformationContext context) { + Value result = null; + if (source instanceof Integer) { + result = new IntegerValue((Integer)source); + } else if (source instanceof Long) { + result = new IntegerValue((Long)source); + } else if (source instanceof Short) { + result = new IntegerValue((Short)source); + } else if (source instanceof Byte) { + result = new IntegerValue((Byte)source); + } else if (source instanceof Double) { + result = new DoubleValue((Double)source); + } else if (source instanceof Float) { + result = new FloatValue((Float)source); + } else if (source instanceof BigDecimal) { + result = new DecimalValue((BigDecimal)source); + } else if (source instanceof String) { + result = new StringValue(((String)source)); + } else { + result = new ObjectValue(source); + } + + return result; + } +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2JavaArray.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2JavaArray.java new file mode 100644 index 0000000000..16d5f524bb --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2JavaArray.java @@ -0,0 +1,74 @@ +/*
+ * 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.databinding.saxon;
+
+import java.lang.reflect.Array;
+
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.value.Value;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+
+/**
+ * Transforms a Value object to a Java Object and return it in an array.
+ *
+ * @version $Rev: 659284 $ $Date: 2008-05-22 14:26:18 -0800 (Thu, 22 May 2008) $
+ */
+public class Value2JavaArray extends BaseTransformer<Value, Object[]> implements PullTransformer<Value, Object[]> {
+
+ public Value2JavaArray() {
+ }
+
+ @Override
+ protected Class<Value> getSourceType() {
+ return Value.class;
+ }
+
+ @Override
+ protected Class<Object[]> getTargetType() {
+ return Object[].class;
+ }
+
+ @Override
+ public int getWeight() {
+ return super.getWeight() + 100;
+ }
+
+ public Object[] transform(Value source, TransformationContext context) {
+
+ try {
+ Object object = Value.convert(Value.asItem(source));
+
+ Class<?> componentClass = context.getTargetDataType().getPhysical().getComponentType();
+ Object[] result = (Object[])Array.newInstance(componentClass, 1);
+
+ result[0] = object;
+
+ return result;
+
+ } catch (XPathException e) {
+ throw new TransformationException(e.getMessage());
+ }
+
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2ObjectTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2ObjectTransformer.java new file mode 100644 index 0000000000..7589f6789b --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2ObjectTransformer.java @@ -0,0 +1,66 @@ +/* + * 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.databinding.saxon; + +import net.sf.saxon.trans.XPathException; +import net.sf.saxon.value.Value; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; + +/** + * Transforms Value objects to generic java objects + * @version $Rev$ $Date$ + */ +public class Value2ObjectTransformer extends BaseTransformer<Value, Object> implements PullTransformer<Value, Object> { + + public Object transform(Value source, TransformationContext context) { + Object object; + try { + object = Value.convert(Value.asItem(source)); + } catch (XPathException e) { + throw new TransformationException(e); + } + return object; + } + + @Override + protected Class<Value> getSourceType() { + return Value.class; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + @Override + public String getTargetDataBinding() { + return JavaBeansDataBinding.NAME; + } + + @Override + public int getWeight() { + return 10000; + } + +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2SimpleTypeTransformer.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2SimpleTypeTransformer.java new file mode 100644 index 0000000000..5da4effcfd --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/Value2SimpleTypeTransformer.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.saxon; + +import net.sf.saxon.trans.XPathException; +import net.sf.saxon.value.Value; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; + +/** + * Transforms Value objects to simple types + * @version $Rev$ $Date$ + */ +public class Value2SimpleTypeTransformer extends BaseTransformer<Value, Object> implements + PullTransformer<Value, Object> { + public Object transform(Value source, TransformationContext context) { + Object object; + try { + object = Value.convert(Value.asItem(source)); + } catch (XPathException e) { + throw new TransformationException(e); + } + return object; + } + + @Override + public String getTargetDataBinding() { + return SimpleJavaDataBinding.NAME; + } + + @Override + protected Class<Value> getSourceType() { + return Value.class; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + @Override + public int getWeight() { + return 10000; + } +} diff --git a/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/collection/ItemList.java b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/collection/ItemList.java new file mode 100644 index 0000000000..065121520b --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/java/org/apache/tuscany/sca/databinding/saxon/collection/ItemList.java @@ -0,0 +1,34 @@ +/*
+ * 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.databinding.saxon.collection;
+
+import java.util.ArrayList;
+
+import net.sf.saxon.om.Item;
+
+/**
+ * Stores a list of Item objects.
+ *
+ * Used by the implementation.xquery to store a collection of results
+ * generated by the xquery execution.
+ *
+ * @version $Rev: 659284 $ $Date: 2008-05-22 14:26:18 -0800 (Thu, 22 May 2008) $
+ */
+public class ItemList extends ArrayList<Item> {}
diff --git a/branches/sca-android/modules/databinding-saxon/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-saxon/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..d895237c7d --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,20 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.saxon.SaxonNodeDataBinding;type=net.sf.saxon.om.NodeInfo,name=saxon_node +org.apache.tuscany.sca.databinding.saxon.SaxonValueDataBinding;type=net.sf.saxon.value.Value,name=saxon_value
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-saxon/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-saxon/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..4d927ce53d --- /dev/null +++ b/branches/sca-android/modules/databinding-saxon/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,34 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.saxon.Node2NodeInfoTransformer;source=org.w3c.dom.Node,target=net.sf.saxon.om.NodeInfo,weight=2000 +org.apache.tuscany.sca.databinding.saxon.NodeInfo2NodeTransformer;source=net.sf.saxon.om.NodeInfo,target=org.w3c.dom.Node,weight=2000 +org.apache.tuscany.sca.databinding.saxon.Object2ValueTransformer;source=java:complexType,target=net.sf.saxon.value.Value,weight=80000 +org.apache.tuscany.sca.databinding.saxon.Value2ObjectTransformer;source=net.sf.saxon.value.Value,target=java:complexType,weight=80000 +org.apache.tuscany.sca.databinding.saxon.SimpleType2ValueTransformer;source=java:simpleType,target=net.sf.saxon.value.Value,weight=80000 +org.apache.tuscany.sca.databinding.saxon.Value2SimpleTypeTransformer;source=net.sf.saxon.value.Value,target=java:simpleType,weight=80000 +org.apache.tuscany.sca.databinding.saxon.NodeInfo2DataObjectTransformer;source=net.sf.saxon.om.NodeInfo,target=commonj.sdo.DataObject,weight=1000 +org.apache.tuscany.sca.databinding.saxon.DataObject2NodeInfoTransformer;source=commonj.sdo.DataObject,target=net.sf.saxon.om.NodeInfo,weight=1000 +org.apache.tuscany.sca.databinding.saxon.ItemList2ObjectTransformer;source=org.apache.tuscany.sca.databinding.saxon.collection.ItemList,target=net.sf.saxon.om.NodeInfo,weight=1000 +org.apache.tuscany.sca.databinding.saxon.ItemList2ObjectTransformer;source=org.apache.tuscany.sca.databinding.saxon.collection.ItemList,target=net.sf.saxon.value.Value,weight=1000 +org.apache.tuscany.sca.databinding.saxon.ItemList2ObjectTransformer;source=org.apache.tuscany.sca.databinding.saxon.collection.ItemList,target=commonj.sdo.DataObject,weight=1000 +org.apache.tuscany.sca.databinding.saxon.ItemList2ObjectTransformer;source=org.apache.tuscany.sca.databinding.saxon.collection.ItemList,target=java:complex,weight=1000 +org.apache.tuscany.sca.databinding.saxon.ItemList2ObjectTransformer;source=org.apache.tuscany.sca.databinding.saxon.collection.ItemList,target=java:simple,weight=1000 +org.apache.tuscany.sca.databinding.saxon.ItemList2ObjectTransformer;source=org.apache.tuscany.sca.databinding.saxon.collection.ItemList,target=java:array,weight=1000 +org.apache.tuscany.sca.databinding.saxon.NodeInfo2JavaArrayTransformer;source=net.sf.saxon.om.NodeInfo,target=java:array,weight=1000 +org.apache.tuscany.sca.databinding.saxon.Value2JavaArrayTransformer;source=net.sf.saxon.value.Value,target=java:array,weight=1000 diff --git a/branches/sca-android/modules/databinding-sdo-axiom/LICENSE b/branches/sca-android/modules/databinding-sdo-axiom/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/branches/sca-android/modules/databinding-sdo-axiom/NOTICE b/branches/sca-android/modules/databinding-sdo-axiom/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-sdo-axiom/pom.xml b/branches/sca-android/modules/databinding-sdo-axiom/pom.xml new file mode 100644 index 0000000000..b63e362616 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/pom.xml @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-sdo-axiom</artifactId> + <name>Apache Tuscany SCA Data Binding for SDO/AXIOM</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding-sdo</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-api</artifactId> + <version>1.2.5</version> + <exclusions> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + <exclusion> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + </exclusion> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + <exclusion> + <groupId>xml-apis</groupId> + <artifactId>xml-apis</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-impl</artifactId> + <version>1.2.5</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + <exclusion> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.0</version> + <executions> + <execution> + <id>add-test-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>target/sdo-source</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.tuscany.sdo</groupId> + <artifactId>tuscany-sdo-plugin</artifactId> + <version>1.1.1</version> + <executions> + <execution> + <id>generate-po-sdo</id> + <phase>generate-sources</phase> + <configuration> + <schemaFile>${basedir}/src/test/resources/ipo.xsd</schemaFile> + <javaPackage>com.example.ipo.sdo</javaPackage> + <noNotification>true</noNotification> + <noContainer>true</noContainer> + <noUnsettable>true</noUnsettable> + </configuration> + <goals> + <goal>generate</goal> + </goals> + </execution> + <execution> + <id>generate-stock-sdo</id> + <phase>generate-sources</phase> + <configuration> + <schemaFile>${basedir}/src/test/resources/stock.xsd</schemaFile> + <javaPackage>com.example.stock.sdo</javaPackage> + <prefix>Stock</prefix> + <noNotification>true</noNotification> + <noContainer>true</noContainer> + <noUnsettable>true</noUnsettable> + </configuration> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.sdo.axiom</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.sdo*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + +</project> diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/AxiomHelper.java b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/AxiomHelper.java new file mode 100644 index 0000000000..02f43000b4 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/AxiomHelper.java @@ -0,0 +1,142 @@ +/* + * 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.databinding.sdo2om; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMDataSource; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.axiom.om.OMXMLParserWrapper; +import org.apache.axiom.om.impl.builder.StAXBuilder; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Helper for AXIOM + * + * @version $Rev$ $Date$ + */ +public class AxiomHelper { + private static final String DEFAULT_PREFIX = "_ns_"; + + private AxiomHelper() { + } + + /** + * See http://issues.apache.org/jira/browse/WSCOMMONS-240 + * @param om + */ + public static void completeAndClose(OMElement om) { + // Get the builder associated with the om element + OMXMLParserWrapper builder = om.getBuilder(); + if (builder != null) { + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).releaseParserOnClose(true); + } + OMElement document = builder.getDocumentElement(); + if (document != null) { + document.build(); + } + } + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).close(); + } + } + + /** + * This method will close the builder immediately. Any subsequent Axiom objects won't + * be built or accessible. + */ + public static void closeImmediately(OMElement om) { + // Get the builder associated with the om element + OMXMLParserWrapper builder = om.getBuilder(); + if (builder != null) { + if (builder instanceof StAXBuilder) { + ((StAXBuilder)builder).releaseParserOnClose(true); + ((StAXBuilder)builder).close(); + } + // builder.close(); + } + } + + /** + * @param context + * @param element + */ + public static void adjustElementName(TransformationContext context, OMElement element) { + if (context != null) { + DataType dataType = context.getTargetDataType(); + Object logical = dataType == null ? null : dataType.getLogical(); + if (!(logical instanceof XMLType)) { + return; + } + XMLType xmlType = (XMLType)logical; + if (xmlType.isElement() && !xmlType.getElementName().equals(element.getQName())) { + // FIXME:: Throw exception or switch to the new Element? + OMFactory factory = OMAbstractFactory.getOMFactory(); + QName name = xmlType.getElementName(); + OMNamespace namespace = factory.createOMNamespace(name.getNamespaceURI(), name.getPrefix()); + element.setNamespace(namespace); + element.setLocalName(name.getLocalPart()); + } + } + } + + public static OMElement createOMElement(OMFactory factory, QName element) { + String localName = element.getLocalPart(); + OMNamespace ns = createOMNamespace(factory, element); + + return factory.createOMElement(localName, ns); + + } + + public static OMElement createOMElement(OMFactory factory, QName element, OMDataSource dataSource) { + String localName = element.getLocalPart(); + OMNamespace ns = createOMNamespace(factory, element); + + return factory.createOMElement(dataSource, localName, ns); + + } + + /** + * @param factory + * @param name + * @return + */ + public static OMNamespace createOMNamespace(OMFactory factory, QName name) { + String namespaceURI = name.getNamespaceURI(); + String prefix = name.getPrefix(); + + OMNamespace ns = null; + if (namespaceURI.length() != 0) { + // Qualified Element: we need an OMNamespace + if (prefix.length() == 0) { + // The prefix does not appear to be specified, let's create one + prefix = DEFAULT_PREFIX; + } + ns = factory.createOMNamespace(namespaceURI, prefix); + } + return ns; + } +} diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/DataObject2OMElement.java b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/DataObject2OMElement.java new file mode 100644 index 0000000000..aa7f99724d --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/DataObject2OMElement.java @@ -0,0 +1,86 @@ +/* + * 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.databinding.sdo2om; + +import static org.apache.tuscany.sca.databinding.sdo.SDODataBinding.ROOT_ELEMENT; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.sdo.SDOContextHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; + +/** + * SDO DataObject --> AXIOM OMElement transformer + * + * @version $Rev$ $Date$ + */ +public class DataObject2OMElement extends BaseTransformer<DataObject, OMElement> implements + PullTransformer<DataObject, OMElement> { + + public OMElement transform(DataObject source, TransformationContext context) { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + OMFactory factory = OMAbstractFactory.getOMFactory(); + + QName name = ROOT_ELEMENT; + if (context != null) { + DataType dataType = context.getTargetDataType(); + Object logical = dataType == null ? null : dataType.getLogical(); + if (logical instanceof XMLType) { + XMLType xmlType = (XMLType)logical; + if (xmlType.isElement()) { + name = xmlType.getElementName(); + } + } + } + + XMLDocument document = helperContext.getXMLHelper().createDocument(source, + name.getNamespaceURI(), + name.getLocalPart()); + SDODataSource dataSource = new SDODataSource(document, helperContext); + OMElement element = AxiomHelper.createOMElement(factory, name, dataSource); + return element; + } + + @Override + protected Class<DataObject> getSourceType() { + return DataObject.class; + } + + @Override + protected Class<OMElement> getTargetType() { + return OMElement.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/SDODataSource.java b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/SDODataSource.java new file mode 100644 index 0000000000..dc3c2610a4 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/SDODataSource.java @@ -0,0 +1,89 @@ +/* + * 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.databinding.sdo2om; + +import static org.apache.tuscany.sca.databinding.sdo.SDODataBinding.ROOT_ELEMENT; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.axiom.om.OMDataSource; +import org.apache.axiom.om.OMOutputFormat; +import org.apache.axiom.om.impl.serialize.StreamingOMSerializer; +import org.apache.tuscany.sdo.api.SDOUtil; +import org.apache.tuscany.sdo.api.XMLStreamHelper; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; + +/** + * + * @version $Rev$ $Date$ + */ +public class SDODataSource implements OMDataSource { + private HelperContext helperContext; + private XMLDocument sourceDocument; + + public SDODataSource(XMLDocument source, HelperContext helperContext) { + this.sourceDocument = source; + this.helperContext = helperContext; + } + + public SDODataSource(DataObject obj, HelperContext helperContext) { + this.helperContext = helperContext; + this.sourceDocument = + helperContext.getXMLHelper().createDocument(obj, + ROOT_ELEMENT.getNamespaceURI(), + ROOT_ELEMENT.getLocalPart()); + } + + public XMLStreamReader getReader() throws XMLStreamException { + XMLStreamHelper streamHelper = SDOUtil.createXMLStreamHelper(helperContext); + return streamHelper.createXMLStreamReader(sourceDocument); + } + + public void serialize(XMLStreamWriter xmlWriter) throws XMLStreamException { + StreamingOMSerializer serializer = new StreamingOMSerializer(); + serializer.serialize(getReader(), xmlWriter); + } + + public void serialize(OutputStream output, OMOutputFormat format) throws XMLStreamException { + try { + helperContext.getXMLHelper().save(sourceDocument, output, null); + } catch (Exception e) { + throw new XMLStreamException(e); + } + } + + public void serialize(Writer writer, OMOutputFormat format) throws XMLStreamException { + try { + helperContext.getXMLHelper().save(sourceDocument, writer, null); + } catch (IOException e) { + throw new XMLStreamException(e); + } + } + +} diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/XMLDocument2OMElement.java b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/XMLDocument2OMElement.java new file mode 100644 index 0000000000..a55a9f37cb --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/main/java/org/apache/tuscany/sca/databinding/sdo2om/XMLDocument2OMElement.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.sdo2om; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.sdo.SDOContextHelper; + +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; + +/** + * SDO XMLDocument --> AXIOM OMElement transformer + * @version $Rev$ $Date$ + */ +public class XMLDocument2OMElement extends BaseTransformer<XMLDocument, OMElement> implements + PullTransformer<XMLDocument, OMElement> { + + public OMElement transform(XMLDocument source, TransformationContext context) { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + SDODataSource dataSource = new SDODataSource(source, helperContext); + OMFactory factory = OMAbstractFactory.getOMFactory(); + QName name = new QName(source.getRootElementURI(), source.getRootElementName()); + OMElement element = AxiomHelper.createOMElement(factory, name, dataSource); + return element; + } + + @Override + protected Class<XMLDocument> getSourceType() { + return XMLDocument.class; + } + + @Override + protected Class<OMElement> getTargetType() { + return OMElement.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-sdo-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..c870ec2406 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,20 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.sdo2om.DataObject2OMElement;source=commonj.sdo.DataObject,target=org.apache.axiom.om.OMElement,weight=3000 +org.apache.tuscany.sca.databinding.sdo2om.XMLDocument2OMElement;source=commonj.sdo.helper.XMLDocument,target=org.apache.axiom.om.OMElement,weight=3000 diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/DataObject2OMElementTestCase.java b/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/DataObject2OMElementTestCase.java new file mode 100644 index 0000000000..57dd056526 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/DataObject2OMElementTestCase.java @@ -0,0 +1,78 @@ +/* + * 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.databinding.sdo2om; + +import java.io.StringWriter; + +import javax.xml.stream.XMLStreamException; + +import junit.framework.Assert; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMNamespace; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import commonj.sdo.DataObject; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataObject2OMElementTestCase extends SDOTransformerTestCaseBase { + + @Override + protected DataType<?> getSourceDataType() { + return new DataTypeImpl<XMLType>(DataObject.class.getName(), DataObject.class, new XMLType(ORDER_QNAME, null)); + } + + @Override + protected DataType<?> getTargetDataType() { + return new DataTypeImpl<XMLType>(OMElement.class.getName(), OMElement.class, new XMLType(ORDER_QNAME, null)); + } + + public final void testTransform() throws XMLStreamException { + OMElement element = new DataObject2OMElement().transform(dataObject, context); + Assert.assertEquals(ORDER_QNAME.getNamespaceURI(), element.getNamespace().getNamespaceURI()); + Assert.assertEquals(ORDER_QNAME.getLocalPart(), element.getLocalName()); + // TODO: See https://issues.apache.org/jira/browse/WSCOMMONS-226 + // element.getBuilder().setCache(false); + StringWriter writer = new StringWriter(); + element.serialize(writer); + } + + public final void testTransformWrapper() throws XMLStreamException { + OMElement element = new DataObject2OMElement().transform(dataObject, context); + Assert.assertEquals(ORDER_QNAME.getNamespaceURI(), element.getNamespace().getNamespaceURI()); + Assert.assertEquals(ORDER_QNAME.getLocalPart(), element.getLocalName()); + + OMNamespace ns = OMAbstractFactory.getOMFactory().createOMNamespace("http://ns1", "ns1"); + element.setNamespace(ns); + element.setLocalName("dummy"); + // TODO: See https://issues.apache.org/jira/browse/WSCOMMONS-226 + // element.getBuilder().setCache(true); + StringWriter writer = new StringWriter(); + element.serializeAndConsume(writer); + // System.out.println(writer); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/SDOTransformerTestCaseBase.java b/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/SDOTransformerTestCaseBase.java new file mode 100644 index 0000000000..f69ef598b8 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/SDOTransformerTestCaseBase.java @@ -0,0 +1,82 @@ +/* + * 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.databinding.sdo2om; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.interfacedef.DataType; + +import com.example.ipo.sdo.PurchaseOrderType; +import com.example.ipo.sdo.SdoFactory; +import com.example.ipo.sdo.USAddress; +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.impl.HelperProvider; + +/** + * The base class for SDO-related test cases + * + * @version $Rev$ $Date$ + */ +public abstract class SDOTransformerTestCaseBase extends TestCase { + protected static final QName ORDER_QNAME = new QName("http://www.example.com/IPO", "purchaseOrder"); + + protected HelperContext helperContext; + protected String binding = DataObject.class.getName(); + protected TransformationContext context; + protected TransformationContext reversedContext; + protected DataObject dataObject; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + helperContext = HelperProvider.getDefaultContext(); + SdoFactory.INSTANCE.register(helperContext); + + context = new TransformationContextImpl(); + context.setSourceDataType(getSourceDataType()); + context.setTargetDataType(getTargetDataType()); + + reversedContext = new TransformationContextImpl(); + reversedContext.setSourceDataType(getTargetDataType()); + reversedContext.setTargetDataType(getSourceDataType()); + + PurchaseOrderType po = SdoFactory.INSTANCE.createPurchaseOrderType(); + USAddress address = SdoFactory.INSTANCE.createUSAddress(); + address.setCity("San Jose"); + address.setStreet("123 ABC St"); + address.setState("CA"); + address.setStreet("95131"); + po.setBillTo(address); + dataObject = (DataObject) po; + } + + protected abstract DataType<?> getSourceDataType(); + + protected abstract DataType<?> getTargetDataType(); + +} diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/XMLDocument2OMElementTestCase.java b/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/XMLDocument2OMElementTestCase.java new file mode 100644 index 0000000000..5015a1b697 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/test/java/org/apache/tuscany/sca/databinding/sdo2om/XMLDocument2OMElementTestCase.java @@ -0,0 +1,63 @@ +/* + * 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.databinding.sdo2om; + +import java.io.StringWriter; + +import javax.xml.stream.XMLStreamException; + +import junit.framework.Assert; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import commonj.sdo.helper.XMLDocument; + +/** + * + * @version $Rev$ $Date$ + */ +public class XMLDocument2OMElementTestCase extends SDOTransformerTestCaseBase { + + @Override + protected DataType<?> getSourceDataType() { + return new DataTypeImpl<XMLType>(XMLDocument.class.getName(), XMLDocument.class, new XMLType(ORDER_QNAME, null)); + } + + @Override + protected DataType<?> getTargetDataType() { + return new DataTypeImpl<XMLType>(OMElement.class.getName(), OMElement.class, new XMLType(ORDER_QNAME, null)); + } + + public final void testTransform() throws XMLStreamException { + XMLDocument document = + helperContext.getXMLHelper().createDocument(dataObject, + ORDER_QNAME.getNamespaceURI(), + ORDER_QNAME.getLocalPart()); + OMElement element = new XMLDocument2OMElement().transform(document, context); + Assert.assertEquals(ORDER_QNAME.getNamespaceURI(), element.getNamespace().getNamespaceURI()); + Assert.assertEquals(ORDER_QNAME.getLocalPart(), element.getLocalName()); + StringWriter writer = new StringWriter(); + element.serialize(writer); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-sdo-axiom/src/test/resources/ipo.xsd new file mode 100644 index 0000000000..241ec15d36 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/test/resources/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-sdo-axiom/src/test/resources/stock.xsd b/branches/sca-android/modules/databinding-sdo-axiom/src/test/resources/stock.xsd new file mode 100644 index 0000000000..a0a6717371 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo-axiom/src/test/resources/stock.xsd @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/stock" xmlns="http://www.w3.org/2001/XMLSchema"> + <!-- Faults --> + <element name="InvalidSymbolFault"> + <complexType> + <sequence> + <element name="message" minOccurs="1" type="string" /> + <element name="symbol" minOccurs="1" type="string" /> + </sequence> + </complexType> + </element> + + <element name="MarketClosedFault" type="string" /> + +</schema>
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-sdo/LICENSE b/branches/sca-android/modules/databinding-sdo/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/branches/sca-android/modules/databinding-sdo/NOTICE b/branches/sca-android/modules/databinding-sdo/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-sdo/pom.xml b/branches/sca-android/modules/databinding-sdo/pom.xml new file mode 100644 index 0000000000..14e353699c --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/pom.xml @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-sdo</artifactId> + <name>Apache Tuscany SCA Data Binding for SDO</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <!-- FIXME: We might want to create a separate module to host the processor --> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-implementation-java-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sdo</groupId> + <artifactId>tuscany-sdo-lib</artifactId> + <version>1.1.1</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sdo</groupId> + <artifactId>tuscany-sdo-impl</artifactId> + <version>1.1.1</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.0</version> + <executions> + <execution> + <id>add-test-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>target/sdo-source</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.tuscany.sdo</groupId> + <artifactId>tuscany-sdo-plugin</artifactId> + <version>1.1.1</version> + <executions> + <execution> + <id>generate-po-sdo</id> + <phase>generate-sources</phase> + <configuration> + <schemaFile>${basedir}/src/test/resources/ipo.xsd</schemaFile> + <javaPackage>com.example.ipo.sdo</javaPackage> + <noNotification>true</noNotification> + <noContainer>true</noContainer> + <noUnsettable>true</noUnsettable> + </configuration> + <goals> + <goal>generate</goal> + </goals> + </execution> + <execution> + <id>generate-stock-sdo</id> + <phase>generate-sources</phase> + <configuration> + <schemaFile>${basedir}/src/test/resources/stock.xsd</schemaFile> + <javaPackage>com.example.stock.sdo</javaPackage> + <prefix>Stock</prefix> + <noNotification>true</noNotification> + <noContainer>true</noContainer> + <noUnsettable>true</noUnsettable> + </configuration> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.sdo</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.sdo*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2Node.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2Node.java new file mode 100644 index 0000000000..503e54e530 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2Node.java @@ -0,0 +1,73 @@ +/* + * 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.databinding.sdo; + +import javax.xml.namespace.QName; +import javax.xml.transform.dom.DOMResult; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XMLHelper; + +public class DataObject2Node extends BaseTransformer<DataObject, Node> implements + PullTransformer<DataObject, Node> { + + public Node transform(DataObject source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + XMLHelper xmlHelper = helperContext.getXMLHelper(); + QName elementName = SDOContextHelper.getElement(context); + Document doc = DOMHelper.newDocument(); + DOMResult result = new DOMResult(doc); + XMLDocument xmlDoc = xmlHelper.createDocument(source, elementName.getNamespaceURI(), elementName.getLocalPart()); + xmlHelper.save(xmlDoc, result, null); + return doc.getDocumentElement(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<DataObject> getSourceType() { + return DataObject.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2String.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2String.java new file mode 100644 index 0000000000..8ce8eae587 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2String.java @@ -0,0 +1,64 @@ +/* + * 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.databinding.sdo; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLHelper; + +public class DataObject2String extends BaseTransformer<DataObject, String> implements + PullTransformer<DataObject, String> { + + public String transform(DataObject source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + XMLHelper xmlHelper = helperContext.getXMLHelper(); + QName elementName = SDOContextHelper.getElement(context); + return xmlHelper.save(source, elementName.getNamespaceURI(), elementName.getLocalPart()); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<DataObject> getSourceType() { + return DataObject.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2XMLStreamReader.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2XMLStreamReader.java new file mode 100644 index 0000000000..116ac4c553 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/DataObject2XMLStreamReader.java @@ -0,0 +1,82 @@ +/* + * 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.databinding.sdo; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sdo.api.SDOUtil; +import org.apache.tuscany.sdo.api.XMLStreamHelper; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XMLHelper; + +public class DataObject2XMLStreamReader extends BaseTransformer<DataObject, XMLStreamReader> implements + PullTransformer<DataObject, XMLStreamReader> { + + public XMLStreamReader transform(final DataObject source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + XMLStreamHelper streamHelper = SDOUtil.createXMLStreamHelper(helperContext); + final QName elementName = SDOContextHelper.getElement(context); + final XMLHelper xmlHelper = helperContext.getXMLHelper(); + // Allow privileged access to read properties. REquires java.util.PropertyPermission + // XML.load.form.lax read in security policy. + XMLDocument document = AccessController.doPrivileged(new PrivilegedAction<XMLDocument>() { + public XMLDocument run() { + return xmlHelper.createDocument(source, elementName.getNamespaceURI(), elementName.getLocalPart()); + } + }); + + return streamHelper.createXMLStreamReader(document); + } catch (XMLStreamException e) { + // TODO: Add context to the exception + throw new TransformationException(e); + } + } + + @Override + protected Class<DataObject> getSourceType() { + return DataObject.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/ImportSDO.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/ImportSDO.java new file mode 100644 index 0000000000..30a3e1c3a9 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/ImportSDO.java @@ -0,0 +1,78 @@ +/* + * 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.databinding.sdo; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.impl.BaseImpl; + +import commonj.sdo.helper.HelperContext; + +/** + * The model object for import.sdo + * + * @version $Rev$ $Date$ + */ +public class ImportSDO extends BaseImpl { + public static final QName IMPORT_SDO = + new QName("http://tuscany.apache.org/xmlns/sca/databinding/sdo/1.0", "import.sdo"); + + private HelperContext helperContext; + private String factoryClassName; + private String schemaLocation; + + public ImportSDO(HelperContext helperContext) { + super(); + this.helperContext = helperContext; + setUnresolved(true); + } + + public HelperContext getHelperContext() { + return helperContext; + } + + /** + * @return the factoryClassName + */ + public String getFactoryClassName() { + return factoryClassName; + } + + /** + * @param factoryClassName the factoryClassName to set + */ + public void setFactoryClassName(String factoryClassName) { + this.factoryClassName = factoryClassName; + } + + /** + * @return the schemaLocation + */ + public String getSchemaLocation() { + return schemaLocation; + } + + /** + * @param schemaLocation the schemaLocation to set + */ + public void setSchemaLocation(String schemaLocation) { + this.schemaLocation = schemaLocation; + } +}
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/ImportSDOProcessor.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/ImportSDOProcessor.java new file mode 100644 index 0000000000..115af19042 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/ImportSDOProcessor.java @@ -0,0 +1,212 @@ +/* + * 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.databinding.sdo; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static org.apache.tuscany.sca.databinding.sdo.ImportSDO.IMPORT_SDO; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLConnection; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.builder.impl.ProblemImpl; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XSDHelper; + +/** + * Loader that handles <import.sdo> elements. + * + * @version $Rev$ $Date$ + * @deprecated + */ +@Deprecated +public class ImportSDOProcessor implements StAXArtifactProcessor<ImportSDO> { + + private ContributionFactory contributionFactory; + private Monitor monitor; + + public ImportSDOProcessor(ModelFactoryExtensionPoint modelFactories, Monitor monitor) { + this.contributionFactory = modelFactories.getFactory(ContributionFactory.class); + this.monitor = monitor; + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "databinding-sdo-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "databinding-sdo-validation-messages", Severity.ERROR, model, message, ex); + monitor.problem(problem); + } + } + + public QName getXMLType() { + return IMPORT_SDO; + } + + public ImportSDO read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + assert IMPORT_SDO.equals(reader.getName()); + + // FIXME: How do we associate the application HelperContext with the one + // imported by the composite + ImportSDO importSDO = new ImportSDO(SDOContextHelper.getDefaultHelperContext()); + String factoryName = reader.getAttributeValue(null, "factory"); + if (factoryName != null) { + importSDO.setFactoryClassName(factoryName); + } + String location = reader.getAttributeValue(null, "location"); + if (location != null) { + importSDO.setSchemaLocation(location); + } + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && ImportSDO.IMPORT_SDO.equals(reader.getName())) { + break; + } + } + return importSDO; + } + + private void importFactory(ImportSDO importSDO, ModelResolver resolver) throws ContributionResolveException { + String factoryName = importSDO.getFactoryClassName(); + if (factoryName != null) { + ClassReference reference = new ClassReference(factoryName); + ClassReference resolved = resolver.resolveModel(ClassReference.class, reference); + if (resolved != null && !resolved.isUnresolved()) { + try { + Class<?> factoryClass = resolved.getJavaClass(); + register(factoryClass, importSDO.getHelperContext()); + importSDO.setUnresolved(false); + } catch (Exception e) { + ContributionResolveException ce = new ContributionResolveException(e); + error("ContributionResolveException", resolver, ce); + //throw ce; + } + } else { + error("FailToResolveClass", resolver, factoryName); + //ContributionResolveException loaderException = + //new ContributionResolveException("Fail to resolve class: " + factoryName); + //throw loaderException; + } + } + } + + private static void register(Class factoryClass, HelperContext helperContext) throws Exception { + Field field = factoryClass.getField("INSTANCE"); + Object factory = field.get(null); + Method method = factory.getClass().getMethod("register", new Class[] {HelperContext.class}); + method.invoke(factory, new Object[] {helperContext}); + + // HelperContext defaultContext = HelperProvider.getDefaultContext(); + // method.invoke(factory, new Object[] {defaultContext}); + } + + private void importWSDL(ImportSDO importSDO, ModelResolver resolver) throws ContributionResolveException { + String location = importSDO.getSchemaLocation(); + if (location != null) { + try { + Artifact artifact = contributionFactory.createArtifact(); + artifact.setURI(location); + artifact = resolver.resolveModel(Artifact.class, artifact); + if (artifact.getLocation() != null) { + String wsdlURL = artifact.getLocation(); + URLConnection connection = new URL(wsdlURL).openConnection(); + connection.setUseCaches(false); + InputStream xsdInputStream = connection.getInputStream(); + try { + XSDHelper xsdHelper = importSDO.getHelperContext().getXSDHelper(); + xsdHelper.define(xsdInputStream, wsdlURL); + } finally { + xsdInputStream.close(); + } + importSDO.setUnresolved(false); + } else { + error("FailToResolveLocation", resolver, location); + //ContributionResolveException loaderException = new ContributionResolveException("Fail to resolve location: " + location); + //throw loaderException; + } + } catch (IOException e) { + ContributionResolveException ce = new ContributionResolveException(e); + error("ContributionResolveException", resolver, ce); + //throw ce; + } + } + } + + public QName getArtifactType() { + return ImportSDO.IMPORT_SDO; + } + + public void write(ImportSDO model, XMLStreamWriter outputSource) throws ContributionWriteException { + // Not implemented as <import.sdo> is deprecated + } + + public Class<ImportSDO> getModelType() { + return ImportSDO.class; + } + + public void resolve(ImportSDO importSDO, ModelResolver resolver) throws ContributionResolveException { + importFactory(importSDO, resolver); + importWSDL(importSDO, resolver); + if (!importSDO.isUnresolved()) { + resolver.addModel(importSDO); + } + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/Node2DataObject.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/Node2DataObject.java new file mode 100644 index 0000000000..4a05492dd8 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/Node2DataObject.java @@ -0,0 +1,69 @@ +/* + * 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.databinding.sdo; + +import javax.xml.transform.dom.DOMSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XMLHelper; + +public class Node2DataObject extends BaseTransformer<Node, DataObject> implements PullTransformer<Node, DataObject> { + + public DataObject transform(Node source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, false); + XMLHelper xmlHelper = helperContext.getXMLHelper(); + Document doc = DOMHelper.promote(source); + DOMSource domSource = new DOMSource(doc); + XMLDocument xmlDoc = xmlHelper.load(domSource, doc.getDocumentURI(), null); + return xmlDoc.getRootObject(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<DataObject> getTargetType() { + return DataObject.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOContextHelper.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOContextHelper.java new file mode 100644 index 0000000000..695722be18 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOContextHelper.java @@ -0,0 +1,208 @@ +/* + * 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.databinding.sdo; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.util.DataTypeHelper; +import org.apache.tuscany.sca.databinding.util.LRUCache; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sdo.api.SDOUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Type; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.TypeHelper; +import commonj.sdo.impl.HelperProvider; + +/** + * Helper class to get TypeHelper from the context + * + * @version $Rev$ $Date$ + */ +public final class SDOContextHelper { + private static final LRUCache<Object, HelperContext> cache = new LRUCache<Object, HelperContext>(1024); + + private SDOContextHelper() { + } + + public static HelperContext getHelperContext(TransformationContext context, boolean source) { + if (context == null) { + return getDefaultHelperContext(); + } + + HelperContext helperContext = null; + Operation op = source ? context.getSourceOperation() : context.getTargetOperation(); + if (op == null) { + DataType<?> dt = source ? context.getSourceDataType() : context.getTargetDataType(); + + helperContext = dt.getMetaData(HelperContext.class); + if (helperContext != null) { + return helperContext; + } + helperContext = SDOUtil.createHelperContext(); + boolean found = register(helperContext, dt); + if (!found) { + helperContext = getDefaultHelperContext(); + } + dt.setMetaData(HelperContext.class, helperContext); + return helperContext; + } else { + return getHelperContext(op); + } + + } + + public static HelperContext getHelperContext(Operation op) { + if (op == null) { + return getDefaultHelperContext(); + } + + HelperContext helperContext = op.getInputType().getMetaData(HelperContext.class); + + if (helperContext != null) { + return helperContext; + } + + // Use the default HelperContext until a type is registered later on + helperContext = getDefaultHelperContext(); + + /* + List<DataType> dataTypes = DataTypeHelper.getDataTypes(op, false); + boolean found = false; + for (DataType d : dataTypes) { + if (register(helperContext, d)) { + found = true; + } + } + if (!found) { + helperContext = getDefaultHelperContext(); + } + */ + op.getInputType().setMetaData(HelperContext.class, helperContext); + return helperContext; + } + + /** + * @param helperContext + * @param dataType + * @return + */ + private static boolean register(HelperContext helperContext, DataType dataType) { + if (dataType == null) { + return false; + } + Set<Class<?>> classes = DataTypeHelper.findClasses(dataType); + boolean found = false; + for (Class<?> cls : classes) { + found = register(helperContext, dataType.getPhysical()) || found; + } + return found; + } + + /** + * FIXME: [rfeng] This is a hack to get the factory out a SDO class + * @param helperContext + * @param javaType + */ + + public static boolean register(HelperContext helperContext, Class javaType) { + if (javaType == null || DataObject.class == javaType) { + return false; + } + try { + Type type = helperContext.getTypeHelper().getType(javaType); + if (type != null && (!type.isDataType())) { + Method method = type.getClass().getMethod("getEPackage"); + Object factory = method.invoke(type, new Object[] {}); + method = factory.getClass().getMethod("register", HelperContext.class); + method.invoke(factory, new Object[] {helperContext}); + return true; + } + return false; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public static HelperContext getDefaultHelperContext() { + // SDOUtil.createHelperContext(); + return HelperProvider.getDefaultContext(); + } + + public static QName getElement(TransformationContext context) { + if (context == null) { + return SDODataBinding.ROOT_ELEMENT; + } + DataType<?> dataType = context.getTargetDataType(); + Object logical = dataType.getLogical(); + QName elementName = null; + if (logical instanceof XMLType) { + XMLType xmlType = (XMLType)logical; + QName element = xmlType.getElementName(); + if (element != null) { + elementName = element; + } + } + if (elementName == null) { + // Try source type + dataType = context.getSourceDataType(); + logical = dataType.getLogical(); + if (logical instanceof XMLType) { + XMLType xmlType = (XMLType)logical; + QName element = xmlType.getElementName(); + if (element != null) { + elementName = element; + } + } + } + if (elementName != null) { + return elementName; + } else { + return SDODataBinding.ROOT_ELEMENT; + } + } + + public static String generateSchema(HelperContext context, Class<?>[] classes) { + TypeHelper typeHelper = context.getTypeHelper(); + List<Type> types = new ArrayList<Type>(); + for (Class<?> cls : classes) { + Type type = typeHelper.getType(cls); + if (type != null) { + types.add(type); + } + } + return generateSchema(context, types); + } + + public static String generateSchema(HelperContext context, List<Type> types) { + // FIXME: SDO throws IllegalArgumentException for types generated from existing XSDs + return context.getXSDHelper().generate(types); + } +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDODataBinding.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDODataBinding.java new file mode 100644 index 0000000000..5a5e35cbbd --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDODataBinding.java @@ -0,0 +1,153 @@ +/* + * 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.databinding.sdo; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sdo.api.SDOUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Type; +import commonj.sdo.helper.CopyHelper; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; + +/** + * SDO Databinding + * + * @version $Rev$ $Date$ + */ +public class SDODataBinding extends BaseDataBinding { + public static final String NAME = DataObject.class.getName(); + public static final String[] ALIASES = new String[] {"sdo"}; + + public static final String ROOT_NAMESPACE = "commonj.sdo"; + public static final QName ROOT_ELEMENT = new QName(ROOT_NAMESPACE, "dataObject"); + + private WrapperHandler<Object> wrapperHandler; + private XMLTypeHelper xmlTypeHelper; + + public SDODataBinding() { + super(NAME, ALIASES, DataObject.class); + wrapperHandler = new SDOWrapperHandler(); + xmlTypeHelper = new SDOTypeHelper(); + } + + @Override + public boolean introspect(DataType dataType, final Operation operation) { + final Class javaType = dataType.getPhysical(); + // Allow privileged access to read system properties. Requires PropertyPermission + // java.specification.version read in security policy. + final HelperContext context = AccessController.doPrivileged(new PrivilegedAction<HelperContext>() { + public HelperContext run() { + return SDOContextHelper.getHelperContext(operation); + } + }); + + Type type = context.getTypeHelper().getType(javaType); + if (type == null) { + // FIXME: Need a better to test dynamic SDO + if (DataObject.class.isAssignableFrom(javaType)) { + // Dynamic SDO + dataType.setDataBinding(getName()); + if (dataType.getLogical() == null) { + dataType.setLogical(XMLType.UNKNOWN); + } + return true; + } + return false; + } + if (type.isDataType()) { + // FIXME: Ignore simple types? + return false; + } + + // Found a SDO type, replace the default context with a private one + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + if (context == SDOContextHelper.getDefaultHelperContext()) { + HelperContext newContext = SDOUtil.createHelperContext(); + SDOContextHelper.register(newContext, javaType); + if (operation != null) { + operation.getInputType().setMetaData(HelperContext.class, newContext); + } + } + return null; + } + }); + + String namespace = type.getURI(); + String name = context.getXSDHelper().getLocalName(type); + QName xmlType = new QName(namespace, name); + dataType.setDataBinding(getName()); + QName elementName = null; + Object logical = dataType.getLogical(); + if (logical instanceof XMLType) { + elementName = ((XMLType)logical).getElementName(); + } + dataType.setLogical(new XMLType(elementName, xmlType)); + + return true; + } + + @Override + public WrapperHandler getWrapperHandler() { + return wrapperHandler; + } + + @Override + public SimpleTypeMapper getSimpleTypeMapper() { + return new SDOSimpleTypeMapper(); + } + + @Override + public XMLTypeHelper getXMLTypeHelper() { + // return new SDOTypeHelper(); + return xmlTypeHelper; + } + + @Override + public Object copy(Object arg, DataType dataType, Operation operation) { + HelperContext context = SDOContextHelper.getHelperContext(operation); + CopyHelper copyHelper = context.getCopyHelper(); + if (arg instanceof XMLDocument) { + XMLDocument document = (XMLDocument)arg; + DataObject dataObject = copyHelper.copy(document.getRootObject()); + return context.getXMLHelper().createDocument(dataObject, + document.getRootElementURI(), + document.getRootElementName()); + } else if (arg instanceof DataObject) { + return context.getCopyHelper().copy((DataObject)arg); + } else { + return super.copy(arg, dataType, operation); + } + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOSimpleTypeMapper.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOSimpleTypeMapper.java new file mode 100644 index 0000000000..c83ec53b01 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOSimpleTypeMapper.java @@ -0,0 +1,68 @@ +/* + * 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.databinding.sdo; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sdo.api.SDOUtil; + +import commonj.sdo.Type; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.TypeHelper; + +/** + * SDO Java/XML mapping for simple XSD types + * + * @version $Rev$ $Date$ + */ +public class SDOSimpleTypeMapper implements SimpleTypeMapper { + public static final String URI_2001_SCHEMA_XSD = "http://www.w3.org/2001/XMLSchema"; + + public SDOSimpleTypeMapper() { + super(); + } + + public Object toJavaObject(QName typeName, String value, TransformationContext context) { + Type type = null; + if (URI_2001_SCHEMA_XSD.equals(typeName.getNamespaceURI())) { + type = SDOUtil.getXSDSDOType(typeName.getLocalPart()); + } else { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, false); + TypeHelper typeHelper = helperContext.getTypeHelper(); + type = typeHelper.getType(typeName.getNamespaceURI(), typeName.getLocalPart()); + } + return SDOUtil.createFromString(type, value); + } + + public String toXMLLiteral(QName typeName, Object obj, TransformationContext context) { + Type type = null; + if (URI_2001_SCHEMA_XSD.equals(typeName.getNamespaceURI())) { + type = SDOUtil.getXSDSDOType(typeName.getLocalPart()); + } else { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + TypeHelper typeHelper = helperContext.getTypeHelper(); + type = typeHelper.getType(typeName.getNamespaceURI(), typeName.getLocalPart()); + } + return SDOUtil.convertToString(type, obj); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOTypeHelper.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOTypeHelper.java new file mode 100644 index 0000000000..c1978883df --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOTypeHelper.java @@ -0,0 +1,235 @@ +/* + * 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.databinding.sdo; + +import java.beans.Introspector; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.xsd.XSDFactory; +import org.apache.tuscany.sca.xsd.XSDefinition; +import org.osoa.sca.ServiceRuntimeException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.bootstrap.DOMImplementationRegistry; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSParser; + +import commonj.sdo.Type; +import commonj.sdo.helper.TypeHelper; +import commonj.sdo.helper.XSDHelper; + +public class SDOTypeHelper implements XMLTypeHelper { + private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; + + private TypeHelper typeHelper; + private XSDHelper xsdHelper; + // private Map<String, List<Type>> xsdTypesMap = new HashMap<String, List<Type>>(); + // private Map<String, List<Type>> typesMap = new HashMap<String, List<Type>>(); + + public SDOTypeHelper() { + super(); + typeHelper = SDOContextHelper.getDefaultHelperContext().getTypeHelper(); + xsdHelper = SDOContextHelper.getDefaultHelperContext().getXSDHelper(); + } + + public TypeInfo getTypeInfo(Class javaType, Object logical) { + QName xmlType = JavaXMLMapper.getXMLType(javaType); + if (xmlType != null) { + return new TypeInfo(xmlType, true, null); + } else { + // introspect(javaType, xsdTypesMap, typesMap); + if (logical instanceof XMLType) { + xmlType = ((XMLType)logical).getTypeName(); + } + if (xmlType == null) { + xmlType = + new QName(JavaXMLMapper.getNamespace(javaType), Introspector.decapitalize(javaType.getSimpleName())); + } + return new TypeInfo(xmlType, false, null); + } + } + + private void introspect(Class javaType, Map<String, List<Type>> xsdTypesMap, Map<String, List<Type>> typesMap) { + Type type = typeHelper.getType(javaType); + if (type == null) { + return; + } + if (xsdHelper.isXSD(type)) { + addToMap(xsdTypesMap, type); + } else { + addToMap(typesMap, type); + } + } + + private void addToMap(Map<String, List<Type>> map, Type type) { + List<Type> types = map.get(type.getURI()); + if (types == null) { + types = new ArrayList<Type>(); + map.put(type.getURI(), types); + } + if (!types.contains(type)) { + types.add(type); + } + } + + /* + public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver) { + List<XSDefinition> definitions = new ArrayList<XSDefinition>(); + generateSDOSchemas(definitions, factory, typesMap); + addResolvedXSDs(definitions, factory, resolver, xsdTypesMap); + return definitions; + } + */ + + private void generateSDOSchemas(List<XSDefinition> definitions, XSDFactory factory, Map<String, List<Type>> map) { + for (Map.Entry<String, List<Type>> entry : map.entrySet()) { + List<Type> types = entry.getValue(); + String ns = entry.getKey(); + generateSchema(definitions, factory, types, ns); + } + } + + private void generateSchema(List<XSDefinition> definitions, XSDFactory factory, List<Type> types, String ns) { + String schema = xsdHelper.generate(types); + DOMImplementationRegistry registry = null; + try { + registry = DOMImplementationRegistry.newInstance(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + DOMImplementation impl = registry.getDOMImplementation("XML 3.0"); + DOMImplementationLS ls = (DOMImplementationLS)impl.getFeature("LS", "3.0"); + LSParser parser = ls.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, SCHEMA_NS); + LSInput input = ls.createLSInput(); + input.setCharacterStream(new StringReader(schema)); + Document document = parser.parse(input); + XSDefinition definition = factory.createXSDefinition(); + definition.setUnresolved(true); + definition.setDocument(document); + definition.setNamespace(ns); + definitions.add(definition); + } + + private void addResolvedXSDs(List<XSDefinition> definitions, + XSDFactory factory, + ModelResolver resolver, + Map<String, List<Type>> map) { + for (Map.Entry<String, List<Type>> entry : map.entrySet()) { + XSDefinition definition = factory.createXSDefinition(); + definition.setUnresolved(true); + definition.setNamespace(entry.getKey()); + //FIXME: set location URI + XSDefinition resolved = resolver.resolveModel(XSDefinition.class, definition); + if (resolved.getSchema() == null) { + //FIXME: create a checked exception and propagate it back up to the activator + throw new RuntimeException("No XSD found for namespace " + entry.getKey()); + } + // make sure all the required types are defined in the resolved schema + for (Type type : entry.getValue()) { + String name = xsdHelper.getLocalName(type); + QName typeName = null; + if (name.endsWith("_._type")) { + // FIXME: Anonymous tyype + name = name.substring(0, name.length() - "_._type".length()); + typeName = new QName(type.getURI(), name); + if (resolved.getXmlSchemaElement(typeName) == null) { + //FIXME: create a checked exception and propagate it back up to the activator + throw new RuntimeException("No XSD found for " + typeName.toString()); + } + } else { + typeName = new QName(type.getURI(), name); + if (resolved.getXmlSchemaType(typeName) == null) { + //FIXME: create a checked exception and propagate it back up to the activator + throw new RuntimeException("No XSD found for " + typeName.toString()); + } + } + + } + definitions.add(resolved); + } + } + + private static List<DataType> getDataTypes(Interface intf) { + List<DataType> dataTypes = new ArrayList<DataType>(); + for (Operation op : intf.getOperations()) { + WrapperInfo wrapper = op.getWrapper(); + if (wrapper != null) { + DataType dt1 = wrapper.getInputWrapperType(); + if (dt1 != null) { + dataTypes.add(dt1); + } + DataType dt2 = wrapper.getOutputWrapperType(); + if (dt2 != null) { + dataTypes.add(dt2); + } + } else { + for (DataType dt1 : op.getInputType().getLogical()) { + dataTypes.add(dt1); + } + DataType dt2 = op.getOutputType(); + if (dt2 != null) { + dataTypes.add(dt2); + } + for (DataType<DataType> dt3 : op.getFaultTypes()) { + DataType dt4 = dt3.getLogical(); + if (dt4 != null) { + dataTypes.add(dt4); + } + } + } + } + return dataTypes; + } + + public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, Interface intf) { + return getSchemaDefinitions(factory, resolver, getDataTypes(intf)); + } + + public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, List<DataType> dataTypes) { + Map<String, List<Type>> xsdTypesMap = new HashMap<String, List<Type>>(); + Map<String, List<Type>> typesMap = new HashMap<String, List<Type>>(); + for (DataType d : dataTypes) { + if (SDODataBinding.NAME.equals(d.getDataBinding())) { + introspect(d.getPhysical(), xsdTypesMap, typesMap); + } + } + List<XSDefinition> definitions = new ArrayList<XSDefinition>(); + generateSDOSchemas(definitions, factory, typesMap); + addResolvedXSDs(definitions, factory, resolver, xsdTypesMap); + return definitions; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOWrapperHandler.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOWrapperHandler.java new file mode 100644 index 0000000000..8a1cd666d8 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/SDOWrapperHandler.java @@ -0,0 +1,177 @@ +/* + * 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.databinding.sdo; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.Sequence; +import commonj.sdo.Type; +import commonj.sdo.helper.DataFactory; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XSDHelper; + +/** + * SDO Wrapper Handler + * + * @version $Rev$ $Date$ + */ +public class SDOWrapperHandler implements WrapperHandler<Object> { + + public Object create(Operation operation, boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + // Class<?> wrapperClass = input ? wrapperInfo.getInputWrapperClass() : wrapperInfo.getOutputWrapperClass(); + HelperContext helperContext = SDOContextHelper.getHelperContext(operation); + Type sdoType = getSDOType(helperContext, element); + if (sdoType != null) { + DataFactory dataFactory = helperContext.getDataFactory(); + return dataFactory.create(sdoType); + } + return null; + } + + public void setChildren(Object wrapper, Object[] childObjects, Operation operation, boolean input) { + List<ElementInfo> childElements = + input ? operation.getWrapper().getInputChildElements() : operation.getWrapper().getOutputChildElements(); + for (int i = 0; i < childElements.size(); i++) { + setChild(wrapper, i, childElements.get(i), childObjects[i]); + } + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#setChild(java.lang.Object, int, ElementInfo, + * java.lang.Object) + */ + public void setChild(Object wrapper, int i, ElementInfo childElement, Object value) { + DataObject wrapperDO = + (wrapper instanceof XMLDocument) ? ((XMLDocument)wrapper).getRootObject() : (DataObject)wrapper; + String name = childElement.getQName().getLocalPart(); + if (childElement.isMany()) { + // FIXME: If we look up by name, we need to make sure the WrapperInfo has the correct element names + wrapperDO.getList(i).addAll((Collection)value); + } else { + wrapperDO.set(i, value); + } + } + + @SuppressWarnings("unchecked") + public List getChildren(Object wrapper, Operation operation, boolean input) { + DataObject wrapperDO = + (wrapper instanceof XMLDocument) ? ((XMLDocument)wrapper).getRootObject() : (DataObject)wrapper; + List<Property> properties = wrapperDO.getInstanceProperties(); + List<Object> elements = new ArrayList<Object>(); + Type type = wrapperDO.getType(); + if (type.isSequenced()) { + // Add values in the sequence + Sequence sequence = wrapperDO.getSequence(); + for (int i = 0; i < sequence.size(); i++) { + // Skip mixed text + if (sequence.getProperty(i) != null) { + elements.add(sequence.getValue(i)); + } + } + } else { + for (Property p : properties) { + Object child = wrapperDO.get(p); + if (p.isMany()) { + for (Object c : (Collection<?>)child) { + elements.add(c); + } + } else { + elements.add(child); + } + } + } + return elements; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getWrapperType(Operation, boolean) + */ + public DataType getWrapperType(Operation operation, boolean input) { + WrapperInfo wrapper = operation.getWrapper(); + ElementInfo element = input ? wrapper.getInputWrapperElement() : wrapper.getOutputWrapperElement(); + HelperContext helperContext = SDOContextHelper.getHelperContext(operation); + Type sdoType = getSDOType(helperContext, element); + if (sdoType != null) { + // Check if child elements matches + Class physical = sdoType.getInstanceClass(); + DataType<XMLType> wrapperType = + new DataTypeImpl<XMLType>(SDODataBinding.NAME, physical, new XMLType(element)); + return wrapperType; + } else { + return null; + } + } + + /** + * @param helperContext + * @param element + * @return + */ + private Type getSDOType(HelperContext helperContext, ElementInfo element) { + XSDHelper xsdHelper = helperContext.getXSDHelper(); + Type sdoType = null; + Property prop = + xsdHelper.getGlobalProperty(element.getQName().getNamespaceURI(), element.getQName().getLocalPart(), true); + if (prop != null) { + sdoType = prop.getType(); + } else { + TypeInfo type = element.getType(); + QName typeName = type != null ? type.getQName() : null; + if (typeName != null) { + sdoType = helperContext.getTypeHelper().getType(typeName.getNamespaceURI(), typeName.getLocalPart()); + } + } + return sdoType; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#isInstance(java.lang.Object, Operation, boolean) + */ + public boolean isInstance(Object wrapper, Operation operation, boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + // List<ElementInfo> childElements = + // input ? wrapperInfo.getInputChildElements() : wrapperInfo.getOutputChildElements(); + HelperContext helperContext = SDOContextHelper.getHelperContext(operation); + Type sdoType = getSDOType(helperContext, element); + if (sdoType != null) { + return sdoType.isInstance(wrapper); + } + return false; + } +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/String2DataObject.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/String2DataObject.java new file mode 100644 index 0000000000..7ac423f8d8 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/String2DataObject.java @@ -0,0 +1,61 @@ +/* + * 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.databinding.sdo; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLHelper; + +public class String2DataObject extends BaseTransformer<String, DataObject> implements + PullTransformer<String, DataObject> { + + public DataObject transform(String source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, false); + XMLHelper xmlHelper = helperContext.getXMLHelper(); + return xmlHelper.load(source).getRootObject(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<DataObject> getTargetType() { + return DataObject.class; + } + + @Override + public int getWeight() { + return 50; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2String.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2String.java new file mode 100644 index 0000000000..4e5aa1d5fd --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2String.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.sdo; + +import java.io.StringWriter; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XMLHelper; + +public class XMLDocument2String extends BaseTransformer<XMLDocument, String> implements + PullTransformer<XMLDocument, String> { + + public String transform(XMLDocument source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + XMLHelper xmlHelper = helperContext.getXMLHelper(); + StringWriter writer = new StringWriter(); + xmlHelper.save(source, writer, null); + return writer.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XMLDocument> getSourceType() { + return XMLDocument.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2XMLStreamReader.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2XMLStreamReader.java new file mode 100644 index 0000000000..e70fa08477 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2XMLStreamReader.java @@ -0,0 +1,69 @@ +/* + * 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.databinding.sdo; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sdo.api.SDOUtil; +import org.apache.tuscany.sdo.api.XMLStreamHelper; + +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; + +public class XMLDocument2XMLStreamReader extends BaseTransformer<XMLDocument, XMLStreamReader> implements + PullTransformer<XMLDocument, XMLStreamReader> { + /** + * @param source + * @param context + * @return + */ + public XMLStreamReader transform(XMLDocument source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, true); + XMLStreamHelper streamHelper = SDOUtil.createXMLStreamHelper(helperContext); + return streamHelper.createXMLStreamReader(source); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XMLDocument> getSourceType() { + return XMLDocument.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLStreamReader2DataObject.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLStreamReader2DataObject.java new file mode 100644 index 0000000000..baf3e2e90a --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLStreamReader2DataObject.java @@ -0,0 +1,72 @@ +/* + * 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.databinding.sdo; + +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sdo.api.SDOUtil; +import org.apache.tuscany.sdo.api.XMLStreamHelper; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; + +public class XMLStreamReader2DataObject extends BaseTransformer<XMLStreamReader, DataObject> implements + PullTransformer<XMLStreamReader, DataObject> { + + public DataObject transform(XMLStreamReader source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, false); + XMLStreamHelper streamHelper = SDOUtil.createXMLStreamHelper(helperContext); + // The XMLStreamHelper requires that the reader is positioned at + // START_ELEMENT + while (source.getEventType() != XMLStreamConstants.START_ELEMENT && source.hasNext()) { + source.next(); + } + DataObject target = streamHelper.loadObject(source); + source.close(); + return target; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<DataObject> getTargetType() { + return DataObject.class; + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 15; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLStreamReader2XMLDocument.java b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLStreamReader2XMLDocument.java new file mode 100644 index 0000000000..ac452910f6 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/java/org/apache/tuscany/sca/databinding/sdo/XMLStreamReader2XMLDocument.java @@ -0,0 +1,66 @@ +/* + * 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.databinding.sdo; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sdo.api.SDOUtil; +import org.apache.tuscany.sdo.api.XMLStreamHelper; + +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; + +public class XMLStreamReader2XMLDocument extends BaseTransformer<XMLStreamReader, XMLDocument> implements + PullTransformer<XMLStreamReader, XMLDocument> { + + public XMLDocument transform(XMLStreamReader source, TransformationContext context) { + if (source == null) { + return null; + } + try { + HelperContext helperContext = SDOContextHelper.getHelperContext(context, false); + XMLStreamHelper streamHelper = SDOUtil.createXMLStreamHelper(helperContext); + XMLDocument target = streamHelper.load(source); + source.close(); + return target; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XMLDocument> getTargetType() { + return XMLDocument.class; + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 15; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..ffe8b895b8 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -0,0 +1,18 @@ +# 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. + +org.apache.tuscany.sca.databinding.sdo.ImportSDOProcessor;qname=http://tuscany.apache.org/xmlns/sca/databinding/sdo/1.0#import.sdo,model=org.apache.tuscany.sca.databinding.sdo.ImportSDO diff --git a/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..afd00b552c --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,19 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.sdo.SDODataBinding;type=commonj.sdo.DataObject,name=sdo
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..b1916fd32a --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,27 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.sdo.DataObject2String;source=commonj.sdo.DataObject,target=java.lang.String,weight=510 +org.apache.tuscany.sca.databinding.sdo.DataObject2XMLStreamReader;source=commonj.sdo.DataObject,target=javax.xml.stream.XMLStreamReader,weight=490 +org.apache.tuscany.sca.databinding.sdo.XMLDocument2String;source=commonj.sdo.helper.XMLDocument,target=java.lang.String,weight=510 +org.apache.tuscany.sca.databinding.sdo.String2DataObject;source=java.lang.String,target=commonj.sdo.DataObject,weight=500 +org.apache.tuscany.sca.databinding.sdo.XMLDocument2XMLStreamReader;source=commonj.sdo.helper.XMLDocument,target=javax.xml.stream.XMLStreamReader,weight=490 +org.apache.tuscany.sca.databinding.sdo.XMLStreamReader2DataObject;source=javax.xml.stream.XMLStreamReader,target=commonj.sdo.DataObject,weight=490 +org.apache.tuscany.sca.databinding.sdo.XMLStreamReader2XMLDocument;source=javax.xml.stream.XMLStreamReader,target=commonj.sdo.helper.XMLDocument,weight=490 +org.apache.tuscany.sca.databinding.sdo.DataObject2Node;source=commonj.sdo.DataObject,target=org.w3c.dom.Node,weight=500 +org.apache.tuscany.sca.databinding.sdo.Node2DataObject;source=org.w3c.dom.Node,target=commonj.sdo.DataObject,weight=500 diff --git a/branches/sca-android/modules/databinding-sdo/src/main/resources/databinding-sdo-validation-messages.properties b/branches/sca-android/modules/databinding-sdo/src/main/resources/databinding-sdo-validation-messages.properties new file mode 100644 index 0000000000..f53f08f377 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/main/resources/databinding-sdo-validation-messages.properties @@ -0,0 +1,23 @@ +# +# +# 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. +# +# +FailToResolveClass = Fail to resolve class: {0} +FailToResolveLocation = Fail to resolve location: {0} +ContributionResolveException = ContributionResolveException occured due to: diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/com/example/stock/sdo/fault/InvalidSymbolFault_Exception.java b/branches/sca-android/modules/databinding-sdo/src/test/java/com/example/stock/sdo/fault/InvalidSymbolFault_Exception.java new file mode 100644 index 0000000000..5a0208b290 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/com/example/stock/sdo/fault/InvalidSymbolFault_Exception.java @@ -0,0 +1,70 @@ +/* + * 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 com.example.stock.sdo.fault; + +import javax.xml.namespace.QName; + +import com.example.stock.sdo.InvalidSymbolFault; + +/** + * Hand-crafted java exception for SDO fault + * + * @version $Rev$ $Date$ + */ +public class InvalidSymbolFault_Exception extends Exception { + private static final long serialVersionUID = 8602157311925253920L; + + /** + * Generated QName for the fault element + */ + public static final QName FAULT_ELEMENT = new QName("http://www.example.com/stock", "InvalidSymbolFault"); + /** + * Java type that goes as soapenv:Fault detail element. + */ + private InvalidSymbolFault faultInfo; + + /** + * @param faultInfo + * @param message + */ + public InvalidSymbolFault_Exception(String message, InvalidSymbolFault faultInfo) { + super(message); + this.faultInfo = faultInfo; + } + + /** + * @param faultInfo + * @param message + * @param cause + */ + public InvalidSymbolFault_Exception(String message, InvalidSymbolFault faultInfo, Throwable cause) { + super(message, cause); + this.faultInfo = faultInfo; + } + + /** + * @return returns fault bean: + * org.apache.tuscany.sca.test.exceptions.impl.jaxb.InvalidSymbolFault + */ + public InvalidSymbolFault getFaultInfo() { + return faultInfo; + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2NodeTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2NodeTestCase.java new file mode 100644 index 0000000000..4bc41a5541 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2NodeTestCase.java @@ -0,0 +1,60 @@ +/* + * 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.databinding.sdo; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import com.example.ipo.sdo.PurchaseOrderType; +import commonj.sdo.DataObject; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataObject2NodeTestCase extends SDOTransformerTestCaseBase { + @Override + protected DataType<?> getSourceDataType() { + return new DataTypeImpl<XMLType>(binding, PurchaseOrderType.class, new XMLType(ORDER_QNAME, null)); + } + + @Override + protected DataType<?> getTargetDataType() { + return new DataTypeImpl<Class<String>>(String.class, String.class); + } + + public final void testTransform() { + Node node = new DataObject2Node().transform(dataObject, context); + Assert.assertNotNull(node); + Element element = (Element) node; + Assert.assertEquals(ORDER_QNAME.getNamespaceURI(), element.getNamespaceURI()); + Assert.assertEquals(ORDER_QNAME.getLocalPart(), element.getLocalName()); + DataObject po = new Node2DataObject().transform(node, reversedContext); + Assert.assertTrue(po instanceof PurchaseOrderType); + PurchaseOrderType orderType = (PurchaseOrderType)po; + Assert.assertEquals("San Jose", orderType.getBillTo().getCity()); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2StringTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2StringTestCase.java new file mode 100644 index 0000000000..44d11cd586 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2StringTestCase.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.sdo; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import com.example.ipo.sdo.PurchaseOrderType; +import commonj.sdo.DataObject; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataObject2StringTestCase extends SDOTransformerTestCaseBase { + @Override + protected DataType<?> getSourceDataType() { + return new DataTypeImpl<XMLType>(binding, PurchaseOrderType.class, new XMLType(ORDER_QNAME, null)); + } + + @Override + protected DataType<?> getTargetDataType() { + return new DataTypeImpl<Class<String>>(String.class, String.class); + } + + public final void testTransform() { + String xml = new DataObject2String().transform(dataObject, context); + Assert.assertTrue(xml.indexOf("<city>San Jose</city>") != -1); + DataObject po = new String2DataObject().transform(xml, reversedContext); + Assert.assertTrue(po instanceof PurchaseOrderType); + PurchaseOrderType orderType = (PurchaseOrderType)po; + Assert.assertEquals("San Jose", orderType.getBillTo().getCity()); + } + + public final void testXML() { + String xml = + "<foo xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + + "xmlns:ipo=\"http://www.example.com/IPO\" xsi:type=\"ipo:USAddress\"/>"; + DataObject dataObject = new String2DataObject().transform(xml, reversedContext); + context.setSourceDataType(new DataTypeImpl<XMLType>(DataObject.class.getName(), DataObject.class, null)); + xml = new DataObject2String().transform(dataObject, context); + Assert.assertTrue(xml.contains("xsi:type=\"ipo:USAddress\"")); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2XMLStreamReaderTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2XMLStreamReaderTestCase.java new file mode 100644 index 0000000000..6a82a7fb18 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/DataObject2XMLStreamReaderTestCase.java @@ -0,0 +1,75 @@ +/* + * 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.databinding.sdo; + +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.xml.Node2String; +import org.apache.tuscany.sca.databinding.xml.XMLStreamReader2Node; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import com.example.ipo.sdo.PurchaseOrderType; +import commonj.sdo.DataObject; +import commonj.sdo.helper.EqualityHelper; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataObject2XMLStreamReaderTestCase extends SDOTransformerTestCaseBase { + + @Override + protected DataType<?> getSourceDataType() { + return new DataTypeImpl<XMLType>(binding, PurchaseOrderType.class, new XMLType(ORDER_QNAME, null)); + } + + @Override + protected DataType<?> getTargetDataType() { + return new DataTypeImpl<Class<XMLStreamReader>>(XMLStreamReader.class, XMLStreamReader.class); + } + + public final void testTransform() throws XMLStreamException { + XMLStreamReader reader = new DataObject2XMLStreamReader().transform(dataObject, context); + while (reader.hasNext()) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + break; + } + } + DataObject d = new XMLStreamReader2DataObject().transform(reader, reversedContext); + assertNotNull(d); + assertTrue(EqualityHelper.INSTANCE.equal(dataObject, d)); + } + + public final void testTransform1() throws XMLStreamException { + XMLStreamReader reader = new DataObject2XMLStreamReader().transform(dataObject, context); + XMLStreamReader2Node t2 = new XMLStreamReader2Node(); + org.w3c.dom.Node node = t2.transform(reader, context); + assertNotNull(node); + Node2String t3 = new Node2String(); + String xml = t3.transform(node, context); + assertTrue(xml.contains("xmlns:xsi")); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/ImportSDOProcessorTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/ImportSDOProcessorTestCase.java new file mode 100644 index 0000000000..fa765f9bf4 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/ImportSDOProcessorTestCase.java @@ -0,0 +1,89 @@ +/* + * 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.databinding.sdo; + +import java.io.StringReader; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +import com.example.ipo.sdo.SdoFactory; + +/** + * @version $Rev$ $Date$ + */ +public class ImportSDOProcessorTestCase extends TestCase { + private static boolean inited; + + private ImportSDOProcessor loader; + private XMLInputFactory xmlFactory; + + public void testMinimal() throws Exception { + String xml = "<import.sdo xmlns='http://tuscany.apache.org/xmlns/sca/databinding/sdo/1.0'/>"; + XMLStreamReader reader = getReader(xml); + assertTrue(loader.read(reader) instanceof ImportSDO); + } + + public void testLocation() throws Exception { + String xml = "<import.sdo xmlns='http://tuscany.apache.org/xmlns/sca/databinding/sdo/1.0' location='ipo.xsd'/>"; + XMLStreamReader reader = getReader(xml); + assertTrue(loader.read(reader) instanceof ImportSDO); + } + + public void testFactory() throws Exception { + String xml = "<import.sdo xmlns='http://tuscany.apache.org/xmlns/sca/databinding/sdo/1.0' " + "factory='" + + MockFactory.class.getName() + + "'/>"; + XMLStreamReader reader = getReader(xml); + assertFalse(inited); + ImportSDO importSDO = loader.read(reader); + assertNotNull(importSDO); + ModelResolver resolver = new TestModelResolver(); + resolver.addModel(new ClassReference(MockFactory.class)); + loader.resolve(importSDO, resolver); + assertTrue(inited); + } + + @Override + protected void setUp() throws Exception { + loader = new ImportSDOProcessor(new DefaultModelFactoryExtensionPoint(), null); + xmlFactory = XMLInputFactory.newInstance(); + } + + protected XMLStreamReader getReader(String xml) throws XMLStreamException { + XMLStreamReader reader = xmlFactory.createXMLStreamReader(new StringReader(xml)); + reader.next(); + return reader; + } + + public static class MockFactory { + public static final Object INSTANCE = SdoFactory.INSTANCE; + + static { + ImportSDOProcessorTestCase.inited = true; + } + } +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOContextHelperTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOContextHelperTestCase.java new file mode 100644 index 0000000000..e0d1c9bf12 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOContextHelperTestCase.java @@ -0,0 +1,55 @@ +/* + * 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.databinding.sdo; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import junit.framework.Assert; + +import org.apache.tuscany.sdo.api.SDOUtil; +import org.junit.Test; + +import commonj.sdo.Type; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.TypeHelper; +import commonj.sdo.helper.XSDHelper; + +/** + * @version $Rev$ $Date$ + */ +public class SDOContextHelperTestCase { + @Test + public void testGenerateSchema() throws IOException { + HelperContext context = SDOUtil.createHelperContext(); + URL url = getClass().getResource("/ipo.xsd"); + Assert.assertNotNull(url); + InputStream is = url.openStream(); + XSDHelper xsdHelper = context.getXSDHelper(); + xsdHelper.define(is, url.toExternalForm()); + TypeHelper typeHelper = context.getTypeHelper(); + Type type = typeHelper.getType("http://www.example.com/IPO", "PurchaseOrderType"); + Assert.assertNotNull(type); + /* + SDOContextHelper.generateSchema(context, Arrays.asList(type)); + */ + } +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDODataBindingTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDODataBindingTestCase.java new file mode 100644 index 0000000000..3c21b56c9f --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDODataBindingTestCase.java @@ -0,0 +1,114 @@ +/* + * 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.databinding.sdo; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import com.example.ipo.sdo.PurchaseOrderType; +import com.example.ipo.sdo.SdoFactory; +import com.example.ipo.sdo.USAddress; +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.impl.HelperProvider; + +/** + * + * @version $Rev$ $Date$ + */ +public class SDODataBindingTestCase extends TestCase { + protected static final QName ORDER_QNAME = new QName("http://www.example.com/IPO", "purchaseOrder"); + private SDODataBinding binding; + private HelperContext context; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + binding = new SDODataBinding(); + context = HelperProvider.getDefaultContext(); + SdoFactory.INSTANCE.register(context); + } + + public final void testIntrospect() { + Operation op = null; + DataType dataType = new DataTypeImpl<Class>(DataObject.class, null); + boolean yes = binding.introspect(dataType, op); + assertTrue(yes); + assertTrue(dataType.getDataBinding().equals(binding.getName())); + assertTrue(dataType.getPhysical() == DataObject.class && dataType.getLogical() == XMLType.UNKNOWN); + dataType = new DataTypeImpl<Class>(PurchaseOrderType.class, null); + yes = binding.introspect(dataType, op); + assertTrue(yes); + assertEquals(PurchaseOrderType.class, dataType.getPhysical()); + assertEquals(new QName("http://www.example.com/IPO", "PurchaseOrderType"), ((XMLType)dataType.getLogical()) + .getTypeName()); + dataType = new DataTypeImpl<Class>(USAddress.class, null); + yes = binding.introspect(dataType, op); + assertTrue(yes); + assertEquals(USAddress.class, dataType.getPhysical()); + assertEquals(new QName("http://www.example.com/IPO", "USAddress"), ((XMLType)dataType.getLogical()) + .getTypeName()); + } + + public final void testCopyRoot() { + PurchaseOrderType po = SdoFactory.INSTANCE.createPurchaseOrderType(); + po.setComment("Comment"); + Object copy = binding.copy(po, null, null); + assertTrue(copy instanceof PurchaseOrderType); + assertTrue(po != copy); + assertTrue(context.getEqualityHelper().equal((DataObject)po, (DataObject)copy)); + assertEquals("Comment", ((PurchaseOrderType)copy).getComment()); + } + + public final void testCopyNonRoot() { + USAddress address = SdoFactory.INSTANCE.createUSAddress(); + address.setCity("San Jose"); + Object copy = binding.copy(address, null, null); + assertTrue(copy instanceof USAddress); + assertTrue(address != copy); + assertTrue(context.getEqualityHelper().equal((DataObject)address, (DataObject)copy)); + assertEquals("San Jose", ((USAddress)copy).getCity()); + } + + public final void testCopyXMLDocument() { + PurchaseOrderType po = SdoFactory.INSTANCE.createPurchaseOrderType(); + po.setComment("Comment"); + XMLDocument doc = + context.getXMLHelper().createDocument((DataObject)po, + ORDER_QNAME.getNamespaceURI(), + ORDER_QNAME.getLocalPart()); + Object copy = binding.copy(doc, null, null); + assertTrue(copy instanceof XMLDocument); + XMLDocument docCopy = (XMLDocument)copy; + assertTrue(doc != copy); + assertTrue(context.getEqualityHelper().equal((DataObject)po, docCopy.getRootObject())); + assertEquals("Comment", ((PurchaseOrderType)docCopy.getRootObject()).getComment()); + } +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOTransformerTestCaseBase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOTransformerTestCaseBase.java new file mode 100644 index 0000000000..2aaae3c6d8 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOTransformerTestCaseBase.java @@ -0,0 +1,82 @@ +/* + * 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.databinding.sdo; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.interfacedef.DataType; + +import com.example.ipo.sdo.PurchaseOrderType; +import com.example.ipo.sdo.SdoFactory; +import com.example.ipo.sdo.USAddress; +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.impl.HelperProvider; + +/** + * The base class for SDO-related test cases + * + * @version $Rev$ $Date$ + */ +public abstract class SDOTransformerTestCaseBase extends TestCase { + protected static final QName ORDER_QNAME = new QName("http://www.example.com/IPO", "purchaseOrder"); + + protected HelperContext helperContext; + protected String binding = DataObject.class.getName(); + protected TransformationContext context; + protected TransformationContext reversedContext; + protected DataObject dataObject; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + helperContext = HelperProvider.getDefaultContext(); + SdoFactory.INSTANCE.register(helperContext); + + context = new TransformationContextImpl(); + context.setSourceDataType(getSourceDataType()); + context.setTargetDataType(getTargetDataType()); + + reversedContext = new TransformationContextImpl(); + reversedContext.setSourceDataType(getTargetDataType()); + reversedContext.setTargetDataType(getSourceDataType()); + + PurchaseOrderType po = SdoFactory.INSTANCE.createPurchaseOrderType(); + USAddress address = SdoFactory.INSTANCE.createUSAddress(); + address.setCity("San Jose"); + address.setStreet("123 ABC St"); + address.setState("CA"); + address.setStreet("95131"); + po.setBillTo(address); + dataObject = (DataObject) po; + } + + protected abstract DataType<?> getSourceDataType(); + + protected abstract DataType<?> getTargetDataType(); + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOWrapperHandlerTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOWrapperHandlerTestCase.java new file mode 100644 index 0000000000..11d8495de8 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/SDOWrapperHandlerTestCase.java @@ -0,0 +1,83 @@ +/* + * 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.databinding.sdo; + +import java.util.List; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sdo.api.SDOUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XMLHelper; +import commonj.sdo.helper.XSDHelper; +import commonj.sdo.impl.HelperProvider; + +/** + * @version $Rev$ $Date$ + */ +public class SDOWrapperHandlerTestCase extends TestCase { + private HelperContext context; + private SDOWrapperHandler handler; + + @Override + public void setUp() throws Exception { + context = SDOUtil.createHelperContext(); + handler = new SDOWrapperHandler(); + } + + public void testWrapperAnyType() throws Exception { + XMLHelper xmlHelper = context.getXMLHelper(); + XMLDocument document = xmlHelper.load(getClass().getResourceAsStream("/wrapper.xml")); + Operation op = new OperationImpl(); + List children = handler.getChildren(document, op, true); + assertEquals(5, children.size()); + } + + public void testWrapper() throws Exception { + XSDHelper xsdHelper = context.getXSDHelper(); + xsdHelper.define(getClass().getResourceAsStream("/wrapper.xsd"), null); + XMLHelper xmlHelper = context.getXMLHelper(); + XMLDocument document = xmlHelper.load(getClass().getResourceAsStream("/wrapper.xml")); + Operation op = new OperationImpl(); + List children = handler.getChildren(document, op, true); + assertEquals(5, children.size()); + } + + public void testCreate() { + HelperContext context = HelperProvider.getDefaultContext(); + XSDHelper xsdHelper = context.getXSDHelper(); + xsdHelper.define(getClass().getResourceAsStream("/wrapper.xsd"), null); + ElementInfo element = new ElementInfo(new QName("http://www.example.com/wrapper", "op"), null); + Operation op = new OperationImpl(); + WrapperInfo wrapperInfo = new WrapperInfo(SDODataBinding.NAME, element, null, null, null); + op.setWrapper(wrapperInfo); + DataObject wrapper = (DataObject) handler.create(op, true); + assertNotNull(wrapper); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/TestModelResolver.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/TestModelResolver.java new file mode 100644 index 0000000000..ce04f5be3f --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/TestModelResolver.java @@ -0,0 +1,63 @@ +/* + * 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.databinding.sdo; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * A default implementation of an artifact resolver, based on a map. + * + * @version $Rev$ $Date$ + */ +public class TestModelResolver implements ModelResolver { + private static final long serialVersionUID = -7826976465762296634L; + + private Map<Object, Object> map = new HashMap<Object, Object>(); + + public TestModelResolver() { + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + } + + public Object removeModel(Object resolved) { + return map.remove(resolved); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2XMLStreamReaderTestCase.java b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2XMLStreamReaderTestCase.java new file mode 100644 index 0000000000..114c568c38 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/java/org/apache/tuscany/sca/databinding/sdo/XMLDocument2XMLStreamReaderTestCase.java @@ -0,0 +1,62 @@ +/* + * 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.databinding.sdo; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import com.example.ipo.sdo.PurchaseOrderType; +import commonj.sdo.helper.XMLDocument; + +/** + * + * @version $Rev$ $Date$ + */ +public class XMLDocument2XMLStreamReaderTestCase extends SDOTransformerTestCaseBase { + + @Override + protected DataType<?> getSourceDataType() { + return new DataTypeImpl<XMLType>(XMLDocument.class.getName(), XMLDocument.class, new XMLType(ORDER_QNAME, null)); + } + + @Override + protected DataType<?> getTargetDataType() { + return new DataTypeImpl<Class<XMLStreamReader>>(XMLStreamReader.class, XMLStreamReader.class); + } + + public final void testTransform() throws XMLStreamException { + XMLDocument document = + helperContext.getXMLHelper().createDocument(dataObject, + ORDER_QNAME.getNamespaceURI(), + ORDER_QNAME.getLocalPart()); + XMLStreamReader reader = new XMLDocument2XMLStreamReader().transform(document, context); + XMLDocument document2 = new XMLStreamReader2XMLDocument().transform(reader, reversedContext); + Assert.assertEquals(ORDER_QNAME.getNamespaceURI(), document2.getRootElementURI()); + Assert.assertEquals(ORDER_QNAME.getLocalPart(), document2.getRootElementName()); + Assert.assertTrue(document2.getRootObject() instanceof PurchaseOrderType); + } + +} diff --git a/branches/sca-android/modules/databinding-sdo/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-sdo/src/test/resources/ipo.xsd new file mode 100755 index 0000000000..241ec15d36 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/resources/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-sdo/src/test/resources/model/sca-core.xsd b/branches/sca-android/modules/databinding-sdo/src/test/resources/model/sca-core.xsd new file mode 100755 index 0000000000..56c6977254 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/resources/model/sca-core.xsd @@ -0,0 +1,233 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<schema xmlns="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://www.osoa.org/xmlns/sca/0.9" + xmlns:sca="http://www.osoa.org/xmlns/sca/0.9" + elementFormDefault="qualified"> + + <element name="componentType" type="sca:ComponentType"/> + <complexType name="ComponentType"> + <sequence> + <element minOccurs="0" maxOccurs="unbounded" name="service" type="sca:Service"/> + <element minOccurs="0" maxOccurs="unbounded" name="reference" type="sca:Reference"/> + <element minOccurs="0" maxOccurs="unbounded" name="property" type="sca:Property"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <complexType name="Service"> + <sequence> + <element minOccurs="1" maxOccurs="1" ref="sca:interface"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <element name="interface" type="sca:Interface"/> + <complexType name="Interface"/> + + <complexType name="Reference"> + <sequence> + <element minOccurs="1" maxOccurs="1" ref="sca:interface"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <attribute name="multiplicity" type="sca:Multiplicity" use="optional" default="1..1"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <complexType name="Property"> + <sequence> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <attribute name="type" type="QName" use="required"/> + <attribute name="many" type="boolean" default="false" use="optional"/> + <attribute name="required" type="boolean" default="false" use="optional"/> + <attribute name="default" type="string" use="optional"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + + <element name="moduleFragment" type="sca:ModuleFragment"/> + <complexType name="ModuleFragment"> + <sequence> + <element minOccurs="0" maxOccurs="unbounded" name="entryPoint" type="sca:EntryPoint"/> + <element minOccurs="0" maxOccurs="unbounded" name="component" type="sca:Component"/> + <element minOccurs="0" maxOccurs="unbounded" name="externalService" type="sca:ExternalService"/> + <element minOccurs="0" maxOccurs="unbounded" name="wire" type="sca:ModuleWire"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <element name="module" type="sca:Module"/> + <complexType name="Module"> + <complexContent> + <extension base="sca:ModuleFragment"/> + </complexContent> + </complexType> + + <complexType name="EntryPoint"> + <sequence> + <element minOccurs="0" maxOccurs="1" ref="sca:interface"/> + <element minOccurs="1" maxOccurs="unbounded" ref="sca:binding"/> + <element minOccurs="1" maxOccurs="unbounded" name="reference" type="anyURI"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <attribute name="multiplicity" type="sca:Multiplicity" use="optional" default="1..1"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + <!-- a multiplicity 1..1 or 0..n sample + <reference>StockQuoteComponent</reference> - type must be URI + a multiplicity 1..n or 0..n sample + <reference>StockQuoteComponent1</reference> - type must be URI + <reference>StockQuoteComponent2</reference> + --> + + <element name="binding" type="sca:Binding"/> + <complexType name="Binding"> + <attribute name="uri" type="anyURI" use="optional"/> + </complexType> + + <complexType name="Component"> + <sequence> + <element minOccurs="1" maxOccurs="1" ref="sca:implementation"/> + <element minOccurs="0" maxOccurs="1" name="properties" type="sca:PropertyValues"/> + <element minOccurs="0" maxOccurs="1" name="references" type="sca:ReferenceValues"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + <!-- a multiplicity 1..1 or 0..1 sample + <references> + <v:stockQuote>StockQuoteComponent</v:stockquote> - type must be URI + </references> + a multiplicity 1..n or 0..n sample + <references> + <v:stockQuote>StockQuoteComponent1</v:stockQuote> - type must be URI + <v:stockQuote>StockQuoteComponent2</v:stockQuote> + </references> + --> + + <element name="implementation" type="sca:Implementation"/> + <complexType name="Implementation"/> + + <complexType name="PropertyValues"> + <sequence> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <complexType name="ReferenceValues"> + <sequence> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + + <complexType name="ExternalService"> + <sequence> + <element minOccurs="1" maxOccurs="1" ref="sca:interface"/> + <element minOccurs="0" maxOccurs="unbounded" ref="sca:binding"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <attribute name="overridable" type="sca:OverrideOptions" default="may" use="optional"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + + <complexType name="ModuleWire"> + <sequence> + <element minOccurs="1" maxOccurs="1" ref="sca:source.uri"/> + <element minOccurs="1" maxOccurs="1" ref="sca:target.uri"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <element name="source" type="anyType"/> + <element name="target" type="anyType"/> + + <element name="source.uri" type="anyURI" substitutionGroup="sca:source"/> + <element name="target.uri" type="anyURI" substitutionGroup="sca:target"/> + + <element name="subsystem" type="sca:Subsystem"/> + <complexType name="Subsystem"> + <sequence> + <element minOccurs="0" maxOccurs="unbounded" name="entryPoint" type="sca:EntryPoint"/> + <element minOccurs="0" maxOccurs="unbounded" name="moduleComponent" type="sca:ModuleComponent"/> + <element minOccurs="0" maxOccurs="unbounded" name="externalService" type="sca:ExternalService"/> + <element minOccurs="0" maxOccurs="unbounded" name="wire" type="sca:SystemWire"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <attribute name="uri" type="anyURI" use="optional"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <complexType name="ModuleComponent"> + <sequence> + <element minOccurs="0" maxOccurs="1" name="properties" type="sca:PropertyValues"/> + <element minOccurs="0" maxOccurs="1" name="references" type="sca:ReferenceValues"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="name" type="NCName" use="required"/> + <attribute name="module" type="NCName" use="required"/> + <attribute name="uri" type="anyURI" use="optional"/> + <anyAttribute namespace="##any" processContents="lax"/> + </complexType> + + <complexType name="SystemWire"> + <sequence> + <element minOccurs="1" maxOccurs="1" ref="sca:source"/> + <element minOccurs="1" maxOccurs="1" ref="sca:target"/> + <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <element name="source.epr" type="anyType" substitutionGroup="sca:source"/> + <element name="target.epr" type="anyType" substitutionGroup="sca:target"/> + + <simpleType name="Multiplicity"> + <restriction base="string"> + <enumeration value="0..1"/> + <enumeration value="1..1"/> + <enumeration value="0..n"/> + <enumeration value="1..n"/> + </restriction> + </simpleType> + + <simpleType name="OverrideOptions"> + <restriction base="string"> + <enumeration value="no"/> + <enumeration value="may"/> + <enumeration value="must"/> + </restriction> + </simpleType> + +</schema> diff --git a/branches/sca-android/modules/databinding-sdo/src/test/resources/model/sca-implementation-mock.xsd b/branches/sca-android/modules/databinding-sdo/src/test/resources/model/sca-implementation-mock.xsd new file mode 100755 index 0000000000..bbaf58f00c --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/resources/model/sca-implementation-mock.xsd @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<schema xmlns="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://www.osoa.org/xmlns/mock/0.9" + elementFormDefault="qualified" + xmlns:mock="http://www.osoa.org/xmlns/mock/0.9" + xmlns:sca="http://www.osoa.org/xmlns/sca/0.9"> + + <import namespace="http://www.osoa.org/xmlns/sca/0.9" + schemaLocation="sca-core.xsd" /> + + <element name="implementation.mock" type="mock:MockImplementation" + substitutionGroup="sca:implementation" /> + <complexType name="MockImplementation"> + <complexContent> + <extension base="sca:Implementation"> + <sequence> + <any namespace="##other" processContents="lax" + minOccurs="0" maxOccurs="unbounded" /> + </sequence> + <attribute name="myAttr" type="NCName" use="required" /> + <anyAttribute namespace="##any" processContents="lax" /> + </extension> + </complexContent> + </complexType> +</schema> diff --git a/branches/sca-android/modules/databinding-sdo/src/test/resources/stock.xsd b/branches/sca-android/modules/databinding-sdo/src/test/resources/stock.xsd new file mode 100644 index 0000000000..a0a6717371 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/resources/stock.xsd @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/stock" xmlns="http://www.w3.org/2001/XMLSchema"> + <!-- Faults --> + <element name="InvalidSymbolFault"> + <complexType> + <sequence> + <element name="message" minOccurs="1" type="string" /> + <element name="symbol" minOccurs="1" type="string" /> + </sequence> + </complexType> + </element> + + <element name="MarketClosedFault" type="string" /> + +</schema>
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-sdo/src/test/resources/wrapper.xml b/branches/sca-android/modules/databinding-sdo/src/test/resources/wrapper.xml new file mode 100644 index 0000000000..2526629409 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/resources/wrapper.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<p:op xmlns:p="http://www.example.com/wrapper" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.example.com/wrapper wrapper.xsd "> + <message>message</message> + <symbol>symbol</symbol> + <message>message1</message> + <symbol>symbol1</symbol> + <symbol>symbol2</symbol> +</p:op> diff --git a/branches/sca-android/modules/databinding-sdo/src/test/resources/wrapper.xsd b/branches/sca-android/modules/databinding-sdo/src/test/resources/wrapper.xsd new file mode 100644 index 0000000000..ea4dc5f7f3 --- /dev/null +++ b/branches/sca-android/modules/databinding-sdo/src/test/resources/wrapper.xsd @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/wrapper" xmlns="http://www.w3.org/2001/XMLSchema"> + <!-- Faults --> + <element name="op"> + <complexType> + <sequence maxOccurs="unbounded"> + <element name="message" minOccurs="1" type="string" /> + <element name="symbol" minOccurs="1" maxOccurs="3" type="string" /> + </sequence> + </complexType> + </element> + + <element name="opResponse"> + <complexType> + <sequence maxOccurs="1"> + <element name="price" minOccurs="1" maxOccurs="unbounded" type="string" /> + </sequence> + </complexType> + </element> +</schema>
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-xmlbeans/LICENSE b/branches/sca-android/modules/databinding-xmlbeans/LICENSE new file mode 100755 index 0000000000..d645695673 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/branches/sca-android/modules/databinding-xmlbeans/NOTICE b/branches/sca-android/modules/databinding-xmlbeans/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding-xmlbeans/pom.xml b/branches/sca-android/modules/databinding-xmlbeans/pom.xml new file mode 100644 index 0000000000..3e92649675 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/pom.xml @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-xmlbeans</artifactId> + <name>Apache Tuscany SCA Data Binding for XmlBeans</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.xmlbeans</groupId> + <artifactId>xmlbeans</artifactId> + <version>2.3.0</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.2</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.0</version> + <executions> + <execution> + <id>add-test-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>target/xmlbeans-source</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + + <dependencies> + <dependency> + <groupId>ant</groupId> + <artifactId>ant-trax</artifactId> + <version>1.6.5</version> + </dependency> + </dependencies> + + <executions> + <execution> + <id>generate-xmlbeans</id> + <phase>generate-sources</phase> + <configuration> + <tasks> + <taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean" + classpathref="maven.compile.classpath" /> + <xmlbean schema="${basedir}/src/test/resources" classpathref="maven.compile.classpath" + destfile="${project.build.directory}/ipo-xmlbeans.jar" + srcgendir="${project.build.directory}/xmlbeans-source" javasource="1.5" + classgendir="${project.build.directory}/test-classes" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.xmlbeans</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.xmlbeans*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/Node2XmlObject.java b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/Node2XmlObject.java new file mode 100644 index 0000000000..e7b240b781 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/Node2XmlObject.java @@ -0,0 +1,61 @@ +/* + * 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.databinding.xmlbeans; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Node; + +/** + * Transforms a DOM Node to an XML Object. + * + * @version $Rev$ $Date$ + */ +public class Node2XmlObject extends BaseTransformer<Node, XmlObject> implements + PullTransformer<Node, XmlObject> { + // private XmlOptions options; + + public XmlObject transform(Node source, TransformationContext context) { + try { + return XmlObject.Factory.parse(source); + } catch (XmlException e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XmlObject> getTargetType() { + return XmlObject.class; + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + public int getWeight() { + return 30; + } + +} diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLBeansDataBinding.java b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLBeansDataBinding.java new file mode 100644 index 0000000000..15616979c2 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLBeansDataBinding.java @@ -0,0 +1,82 @@ +/* + * 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.databinding.xmlbeans; + +import java.lang.reflect.Field; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.xmlbeans.SchemaType; +import org.apache.xmlbeans.XmlObject; +import org.osoa.sca.ServiceRuntimeException; + +/** + * XMLBeans DataBinding + * + * @version $Rev$ $Date$ + */ +public class XMLBeansDataBinding extends BaseDataBinding { + public static final String NAME = XmlObject.class.getName(); + public static final String[] ALIASES = {"xmlbeans"}; + + public XMLBeansDataBinding() { + super(NAME, XmlObject.class); + } + + @Override + public WrapperHandler getWrapperHandler() { + return new XMLBeansWrapperHandler(); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (XmlObject.class.isAssignableFrom(type.getPhysical())) { + Class<?> cls = type.getPhysical(); + SchemaType schemaType = null; + try { + Field f = cls.getField("type"); + schemaType = (SchemaType)f.get(null); + } catch (Throwable e) { + throw new ServiceRuntimeException(e); + } + QName typeName = schemaType.getName(); + Object logical = type.getLogical(); + QName elementName = null; + if (logical instanceof XMLType) { + elementName = ((XMLType)logical).getElementName(); + } + type.setLogical(new XMLType(elementName, typeName)); + type.setMetaData(SchemaType.class, schemaType); + return true; + } + return false; + } + + @Override + public Object copy(Object object, DataType dataType, Operation operation) { + return ((XmlObject)object).copy(); + } + +} diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLBeansWrapperHandler.java b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLBeansWrapperHandler.java new file mode 100644 index 0000000000..506c42e40f --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLBeansWrapperHandler.java @@ -0,0 +1,110 @@ +/* + * 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.databinding.xmlbeans; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.xmlbeans.SchemaProperty; +import org.apache.xmlbeans.SimpleValue; +import org.apache.xmlbeans.XmlObject; + +/** + * @version $Rev$ $Date$ + */ +public class XMLBeansWrapperHandler implements WrapperHandler<XmlObject> { + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#create(org.apache.tuscany.sca.interfacedef.Operation, boolean) + */ + public XmlObject create(Operation operation, boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getChildren(java.lang.Object, org.apache.tuscany.sca.interfacedef.Operation, boolean) + */ + public List getChildren(XmlObject wrapper, Operation operation, boolean input) { + List<Object> children = new ArrayList<Object>(); + + List<ElementInfo> childElements = + input ? operation.getWrapper().getInputChildElements() : operation.getWrapper().getOutputChildElements(); + for (ElementInfo e : childElements) { + XmlObject[] objects = wrapper.selectChildren(e.getQName()); + if (objects != null && objects.length == 1) { + if (objects[0] instanceof SimpleValue) { + children.add(((SimpleValue)objects[0]).getObjectValue()); + } else { + children.add(objects[0]); + } + } + // FIXME: What should we do for many-value? + } + return children; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getWrapperType(org.apache.tuscany.sca.interfacedef.Operation, boolean) + */ + public DataType getWrapperType(Operation operation, boolean input) { + // TODO Auto-generated method stub + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#isInstance(java.lang.Object, org.apache.tuscany.sca.interfacedef.Operation, boolean) + */ + public boolean isInstance(Object wrapper, Operation operation, boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + return true; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#setChildren(java.lang.Object, java.lang.Object[], org.apache.tuscany.sca.interfacedef.Operation, boolean) + */ + public void setChildren(XmlObject wrapper, Object[] childObjects, Operation operation, boolean input) { + List<ElementInfo> childElements = + input ? operation.getWrapper().getInputChildElements() : operation.getWrapper().getOutputChildElements(); + int i = 0; + for (ElementInfo c : childElements) { + SchemaProperty property = wrapper.schemaType().getElementProperty(c.getQName()); + + String prop = property.getJavaPropertyName(); + + Method setter; + try { + setter = wrapper.schemaType().getJavaClass().getMethod("set" + prop, property.getType().getJavaClass()); + setter.invoke(wrapper, childObjects[i++]); + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + } + +} diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLStreamReader2XmlObject.java b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLStreamReader2XmlObject.java new file mode 100644 index 0000000000..ca84f961b1 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XMLStreamReader2XmlObject.java @@ -0,0 +1,62 @@ +/* + * 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.databinding.xmlbeans; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.xmlbeans.XmlObject; + +/** + * Transforms an XMLStreamReader to an XML Object. + * + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2XmlObject extends BaseTransformer<XMLStreamReader, XmlObject> implements PullTransformer<XMLStreamReader, XmlObject> { + // private XmlOptions options; + + public XmlObject transform(XMLStreamReader source, TransformationContext context) { + try { + XmlObject target = XmlObject.Factory.parse(source); + source.close(); + return target; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XmlObject> getTargetType() { + return XmlObject.class; + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObject2Node.java b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObject2Node.java new file mode 100644 index 0000000000..c820d9d250 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObject2Node.java @@ -0,0 +1,60 @@ +/* + * 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.databinding.xmlbeans; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.Transformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.xmlbeans.XmlObject; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Transforms an XML Object to a DOM Node. + * + * @version $Rev$ $Date$ + */ +@Service(Transformer.class) +public class XmlObject2Node extends BaseTransformer<XmlObject, Node> implements + PullTransformer<XmlObject, Node> { + // private XmlOptions options; + + public Node transform(XmlObject source, TransformationContext context) { + if (source == null) + return null; + return source.newDomNode(); + } + + @Override + protected Class<XmlObject> getSourceType() { + return XmlObject.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 30; + } + +} diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObject2XMLStreamReader.java b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObject2XMLStreamReader.java new file mode 100644 index 0000000000..bbffb7d748 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObject2XMLStreamReader.java @@ -0,0 +1,55 @@ +/* + * 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.databinding.xmlbeans; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.xmlbeans.XmlObject; + +/** + * Transforms an XML Object to an XMLStreamReader. + * + * @version $Rev$ $Date$ + */ +public class XmlObject2XMLStreamReader extends BaseTransformer<XmlObject, XMLStreamReader> implements PullTransformer<XmlObject, XMLStreamReader> { + // private XmlOptions options; + + public XMLStreamReader transform(XmlObject source, TransformationContext context) { + return source.newXMLStreamReader(); + } + + @Override + protected Class<XmlObject> getSourceType() { + return XmlObject.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-xmlbeans/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..907d06559a --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,19 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.xmlbeans.XMLBeansDataBinding;type=org.apache.xmlbeans.XmlObject,name=xmlbeans
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-xmlbeans/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..4e419de051 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,22 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.xmlbeans.Node2XmlObject;source=org.w3c.dom.Node,target=org.apache.xmlbeans.XmlObject,weight=500 +org.apache.tuscany.sca.databinding.xmlbeans.XmlObject2Node;source=org.apache.xmlbeans.XmlObject,target=org.w3c.dom.Node,weight=500 +org.apache.tuscany.sca.databinding.xmlbeans.XmlObject2XMLStreamReader;source=org.apache.xmlbeans.XmlObject,target=javax.xml.stream.XMLStreamReader,weight=490 +org.apache.tuscany.sca.databinding.xmlbeans.XMLStreamReader2XmlObject;source=javax.xml.stream.XMLStreamReader,target=org.apache.xmlbeans.XmlObject,weight=490 diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/test/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObjectTestCase.java b/branches/sca-android/modules/databinding-xmlbeans/src/test/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObjectTestCase.java new file mode 100644 index 0000000000..7b98ddb021 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/test/java/org/apache/tuscany/sca/databinding/xmlbeans/XmlObjectTestCase.java @@ -0,0 +1,105 @@ +/* + * 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.databinding.xmlbeans; + +import java.io.StringReader; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Node; + +import com.example.ipo.xmlbeans.PurchaseOrderDocument; + +/** + * Test cases for testing XML Object transformations. + * + * @version $Rev$ $Date$ + */ +public class XmlObjectTestCase extends TestCase { + private static final String IPO_XML = "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + " <name>Helen Zoe</name>" + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + " <postcode>CB1 1JR</postcode>" + " </shipTo>" + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + " <street>8 Oak Avenue</street>" + " <city>Old Town</city>" + " <state>PA</state>" + + " <zip>95819</zip>" + " </billTo>" + " <items>" + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + " <quantity>1</quantity>" + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + " <shipDate>1999-12-05</shipDate>" + " </item>" + " </items>" + + "</ipo:purchaseOrder>"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testXmlObject() throws Exception { + // URL/Stream/Reader to XmlObject + XmlObject object = XmlObject.Factory.parse(new StringReader(IPO_XML)); + + // XmlObject to XMLStreamReader + XmlObject2XMLStreamReader t1 = new XmlObject2XMLStreamReader(); + XMLStreamReader reader = t1.transform(object, null); + + // XMLStreamReader to XmlObject + XMLStreamReader2XmlObject t2 = new XMLStreamReader2XmlObject(); + XmlObject object2 = t2.transform(reader, null); + + // XmlObject to Node + XmlObject2Node t3 = new XmlObject2Node(); + Node node = t3.transform(object2, null); + + // Node to XmlObject + Node2XmlObject t4 = new Node2XmlObject(); + XmlObject object3 = t4.transform(node, null); + Assert.assertNotNull(object3); + } + + public void testGeneratedXmlObject() throws Exception { + // URL xmlFile = getClass().getClassLoader().getResource("ipo.xml"); + // URL/Stream/Reader to XmlObject + PurchaseOrderDocument object = PurchaseOrderDocument.Factory.parse(new StringReader(IPO_XML)); + + // XmlObject to XMLStreamReader + XmlObject2XMLStreamReader t1 = new XmlObject2XMLStreamReader(); + XMLStreamReader reader = t1.transform(object, null); + + // XMLStreamReader to XmlObject + XMLStreamReader2XmlObject t2 = new XMLStreamReader2XmlObject(); + PurchaseOrderDocument object2 = (PurchaseOrderDocument) t2.transform(reader, null); + + // XmlObject to Node + XmlObject2Node t3 = new XmlObject2Node(); + Node node = t3.transform(object2, null); + + // Node to XmlObject + Node2XmlObject t4 = new Node2XmlObject(); + PurchaseOrderDocument object3 = (PurchaseOrderDocument) t4.transform(node, null); + Assert.assertNotNull(object3); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + +} diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-xmlbeans/src/test/resources/ipo.xsd new file mode 100755 index 0000000000..5a493e1746 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/test/resources/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-xmlbeans/src/test/resources/ipo.xsdconfig b/branches/sca-android/modules/databinding-xmlbeans/src/test/resources/ipo.xsdconfig new file mode 100755 index 0000000000..a397182672 --- /dev/null +++ b/branches/sca-android/modules/databinding-xmlbeans/src/test/resources/ipo.xsdconfig @@ -0,0 +1,21 @@ +<!-- Copyright 2004 The Apache Software Foundation + + 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. --> +<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config" + xmlns:ipo="http://www.example.com/IPO"> + + <xb:namespace uri="http://www.example.com/IPO"> + <xb:package>com.example.ipo.xmlbeans</xb:package> + </xb:namespace> + +</xb:config> diff --git a/branches/sca-android/modules/databinding-xstream/LICENSE b/branches/sca-android/modules/databinding-xstream/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/LICENSE @@ -0,0 +1,205 @@ +
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
+
+
diff --git a/branches/sca-android/modules/databinding-xstream/NOTICE b/branches/sca-android/modules/databinding-xstream/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/NOTICE @@ -0,0 +1,6 @@ +${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/branches/sca-android/modules/databinding-xstream/pom.xml b/branches/sca-android/modules/databinding-xstream/pom.xml new file mode 100644 index 0000000000..34faa5c8bb --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/pom.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-xstream</artifactId> + <name>Apache Tuscany SCA Data Binding for XStream</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>javax.xml.stream</groupId> + <artifactId>stax-api</artifactId> + <version>1.0-2</version> + </dependency> + + <dependency> + <groupId>com.thoughtworks.xstream</groupId> + <artifactId>xstream</artifactId> + <version>1.3</version> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-api</artifactId> + <exclusions> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + </exclusions> + <version>1.2.5</version> + </dependency> + + <dependency> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + <version>2.8.1</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.axiom</groupId> + <artifactId>axiom-impl</artifactId> + <version>1.2.5</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>wstx-asl</artifactId> + <version>3.2.1</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding.xstream</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding.xstream*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/MetaObject.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/MetaObject.java new file mode 100644 index 0000000000..4c57cfe06b --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/MetaObject.java @@ -0,0 +1,37 @@ +/* + * 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.databinding.xstream; + +/** + * Wrapper for XObject + * @version $Rev$ $Date$ + */ +public interface MetaObject { + void setName(String name); + + String getName(); + + Class<?> getType(); + + String getID(); + + XObject getInstance(); + //byte[] getByteCode(); +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/MetaObjectImpl.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/MetaObjectImpl.java new file mode 100644 index 0000000000..d223a4db23 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/MetaObjectImpl.java @@ -0,0 +1,95 @@ +/* + * 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.databinding.xstream; + +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * Implementation of a wrapper for XObject. + * + * @version $Rev$ $Date$ + */ +public class MetaObjectImpl implements MetaObject { + private String obID; + private String name; + private XObject obInstance; + + //private byte[] bytecode = null; + + public MetaObjectImpl() { + this.obID = Utils.uniqueID(); + } + + public MetaObjectImpl(XObject x) { + //this.name = path; + this.obID = Utils.uniqueID(); + this.obInstance = x; + + try { + initMetaOb(this.obInstance.getClass()); + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private void initMetaOb(Class<?> class1) throws FileNotFoundException, IOException { + /* + File file = new File(cname); + DataInputStream cstream = new DataInputStream(new FileInputStream(file)); + bytecode = new byte[(int)file.length()]; + cstream.readFully(bytecode); + */ + name = class1.getName(); + + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getID() { + return obID; + } + + public Class<?> getType() { + + return this.obInstance.getClass(); + } + + public XObject getInstance() { + return this.obInstance; + } + /* + * TODO Add bytecode with Serialization + public byte[] getByteCode() { + return bytecode; + } + */ + +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/Node2XObject.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/Node2XObject.java new file mode 100644 index 0000000000..2b7fa9d506 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/Node2XObject.java @@ -0,0 +1,69 @@ +/* + * 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.databinding.xstream; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomReader; + +/** + * DOM Node --> XStream transformer + * + * @version $Rev$ $Date$ + */ +public class Node2XObject extends BaseTransformer<Node, XObject> implements PullTransformer<Node, XObject> { + + public XObject transform(Node source, TransformationContext context) { + try { + DomReader in = null; + if (source instanceof Document) { + in = new DomReader((Document)source); + } else if (source instanceof Element) { + in = new DomReader((Element)source); + } + XStream xs = new XStream(); + return (XObject)xs.unmarshal(in); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<Node> getSourceType() { + return Node.class; + } + + @Override + public Class<XObject> getTargetType() { + return XObject.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/OMElement2XObject.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/OMElement2XObject.java new file mode 100644 index 0000000000..a465e92e65 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/OMElement2XObject.java @@ -0,0 +1,76 @@ +/* + * 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.databinding.xstream; + +import java.io.StringWriter; + +import javax.xml.stream.XMLStreamException; + +import org.apache.axiom.om.OMElement; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +import com.thoughtworks.xstream.XStream; + +/** + * Job DataObject --> AXIOM OMElement transformer + * + * @version $Rev$ $Date$ + */ +public class OMElement2XObject extends BaseTransformer<OMElement, XObject> implements + PullTransformer<OMElement, XObject> { + + public XObject transform(OMElement source, TransformationContext context) { + + XStream xs = new XStream(); + xs.alias("xobject", MetaObjectImpl.class); + MetaObjectImpl mo; + try { + java.io.StringWriter writer = new StringWriter(); + source.serialize(writer); + String w = writer.toString(); + // FIXME: a better way to get eliminate param0 + w = w.replaceAll("param0", "xobject"); + w = w.replaceAll("xmlns=\"\"", ""); + mo = (MetaObjectImpl)xs.fromXML(w.trim()); + return mo.getInstance(); + } catch (XMLStreamException e) { + + e.printStackTrace(); + } + return null; + } + + @Override + public Class<OMElement> getSourceType() { + return OMElement.class; + } + + @Override + public Class<XObject> getTargetType() { + return XObject.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/Utils.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/Utils.java new file mode 100644 index 0000000000..d819975910 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/Utils.java @@ -0,0 +1,79 @@ +/* + * 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.databinding.xstream; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * Utility methods. + * + * @version $Rev$ $Date$ + */ +public class Utils { + public static String toBase64(byte[] array) { + String code = null; + code = new sun.misc.BASE64Encoder().encode(array); + return code; + } + + public static byte[] fromBase64(String bytecode) { + byte[] dec = null; + try { + dec = new sun.misc.BASE64Decoder().decodeBuffer(bytecode); + } catch (IOException e) { + e.printStackTrace(); + } + return dec; + } + + public static String uniqueID() { + try { + //Initialize SecureRandom + //This is a lengthy operation, to be done only upon + //initialization of the application + SecureRandom prng = SecureRandom.getInstance("SHA1PRNG"); + + //generate a random number + String randomNum = Integer.toString(prng.nextInt()); + + //get its digest + MessageDigest sha = MessageDigest.getInstance("SHA-1"); + byte[] result = sha.digest(randomNum.getBytes()); + return hexEncode(result); + } catch (NoSuchAlgorithmException ex) { + ex.printStackTrace(); + } + return null; + } + + private static String hexEncode(byte[] aInput) { + StringBuffer result = new StringBuffer(); + char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + for (int idx = 0; idx < aInput.length; ++idx) { + byte b = aInput[idx]; + result.append(digits[(b & 0xf0) >> 4]); + result.append(digits[b & 0x0f]); + } + return result.toString(); + } + +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject.java new file mode 100644 index 0000000000..21112efcf5 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject.java @@ -0,0 +1,28 @@ +/* + * 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.databinding.xstream; + +/** + * Marker interface for XStream Serializable objects + * + * @version $Rev$ $Date$ + */ +// FIXME: Why do we require a marker interface? +public interface XObject { +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject2Node.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject2Node.java new file mode 100644 index 0000000000..98e0e69f9b --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject2Node.java @@ -0,0 +1,69 @@ +/* + * 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.databinding.xstream; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomWriter; + +/** + * XObject --> DOM Node transformer + * + * @version $Rev$ $Date$ + */ +public class XObject2Node extends BaseTransformer<XObject, Node> implements PullTransformer<XObject, Node> { + + public Node transform(XObject source, TransformationContext context) { + try { + MetaObject mj = new MetaObjectImpl(source); + Document root = DOMHelper.newDocument(); + DomWriter out = new DomWriter(DOMHelper.newDocument()); + XStream xs = new XStream(); + xs.alias("xobject", mj.getClass()); + xs.marshal(source, out); + DOMHelper.adjustElementName(context, root.getDocumentElement()); + return root; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<XObject> getSourceType() { + return XObject.class; + } + + @Override + public Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject2OMElement.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject2OMElement.java new file mode 100644 index 0000000000..ff4305491a --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObject2OMElement.java @@ -0,0 +1,106 @@ +/* + * 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.databinding.xstream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +import com.thoughtworks.xstream.XStream; + +/** + * XObject --> AXIOM OMElement transformer + * + * @version $Rev$ $Date$ + */ +public class XObject2OMElement extends BaseTransformer<XObject, OMElement> implements + PullTransformer<XObject, OMElement> { + + public OMElement transform(XObject source, TransformationContext context) { + MetaObject mj = new MetaObjectImpl(source); + OMElement element = null; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XStream xs = new XStream(); + xs.alias("xobject", mj.getClass()); + xs.toXML(mj, out); + /* TODO: Maybe a base64 conversion...? or not? + * ie. new ByteArrayInputStream(Utils.toBase64(out.toByteArray()).getBytes()) + */ + try { + // what's better this one: + StAXOMBuilder builder = new StAXOMBuilder(new ByteArrayInputStream(out.toByteArray())); + // or this one: + // StaAXOMBuilder builder = new StAXOMBuilder(new ByteArrayInputStream(Utils.toBase64(out.toByteArray()).getBytes())) + element = builder.getDocumentElement(); + adjustElementName(context, element); + } catch (Exception e) { + throw new TransformationException(e); + } + return element; + + } + + private static void adjustElementName(TransformationContext context, OMElement element) { + if (context != null) { + DataType dataType = context.getTargetDataType(); + Object logical = dataType == null ? null : dataType.getLogical(); + if (!(logical instanceof XMLType)) { + return; + } + XMLType xmlType = (XMLType)logical; + if (xmlType.isElement() && !xmlType.getElementName().equals(element.getQName())) { + // FIXME:: Throw exception or switch to the new Element? + OMFactory factory = OMAbstractFactory.getOMFactory(); + QName name = xmlType.getElementName(); + OMNamespace namespace = factory.createOMNamespace(name.getNamespaceURI(), name.getPrefix()); + element.setNamespace(namespace); + element.setLocalName(name.getLocalPart()); + } + } + } + + @Override + public Class<XObject> getSourceType() { + return XObject.class; + } + + @Override + public Class<OMElement> getTargetType() { + return OMElement.class; + } + + @Override + public int getWeight() { + return 10; + } + +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObjectDataBinding.java b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObjectDataBinding.java new file mode 100644 index 0000000000..6e5ac29423 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/java/org/apache/tuscany/sca/databinding/xstream/XObjectDataBinding.java @@ -0,0 +1,38 @@ +/* + * 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.databinding.xstream; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; + +/** + * DataBinding for Jobs + * + * @version $Rev$ $Date$ + */ +public class XObjectDataBinding extends BaseDataBinding { + + public static final String NAME = XObject.class.getName(); + public static final String[] ALIASES = new String[] {"xobject"}; + + public XObjectDataBinding() { + super(NAME, ALIASES, XObject.class); + } + +} diff --git a/branches/sca-android/modules/databinding-xstream/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding-xstream/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..f501ef2dc6 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,20 @@ +# 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.
+
+# implementation classes for the databindings
+org.apache.tuscany.sca.databinding.xstream.XObjectDataBinding;type=org.apache.tuscany.sca.databinding.xstream.XObject,name=xobject
+
diff --git a/branches/sca-android/modules/databinding-xstream/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding-xstream/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..a733ad7b7d --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,18 @@ +# 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.
+org.apache.tuscany.sca.databinding.xstream.XObject2OMElement;source=org.apache.tuscany.sca.databinding.xstream.XObject,target=org.apache.axiom.om.OMElement,weight=10
+org.apache.tuscany.sca.databinding.xstream.OMElement2XObject;source=org.apache.axiom.om.OMElement,target=org.apache.tuscany.sca.databinding.xstream.XObject,weight=10
diff --git a/branches/sca-android/modules/databinding-xstream/src/test/resources/ipo.xml b/branches/sca-android/modules/databinding-xstream/src/test/resources/ipo.xml new file mode 100644 index 0000000000..1699538d62 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/test/resources/ipo.xml @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<ipo:purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ipo="http://www.example.com/IPO" + xsi:schemaLocation="http://www.example.com/IPO ipo.xsd" orderDate="1999-12-01"> + + <shipTo exportCode="1" xsi:type="ipo:UKAddress"> + <name>Helen Zoe</name> + <street>47 Eden Street</street> + <city>Cambridge</city> + <postcode>CB1 1JR</postcode> + </shipTo> + + <billTo xsi:type="ipo:USAddress"> + <name>Robert Smith</name> + <street>8 Oak Avenue</street> + <city>Old Town</city> + <state>PA</state> + <zip>95819</zip> + </billTo> + + <items> + <item partNum="833-AA"> + <productName>Lapis necklace</productName> + <quantity>1</quantity> + <USPrice>99.95</USPrice> + <ipo:comment>Want this for the holidays</ipo:comment> + <shipDate>1999-12-05</shipDate> + </item> + </items> +</ipo:purchaseOrder> + diff --git a/branches/sca-android/modules/databinding-xstream/src/test/resources/ipo.xsd b/branches/sca-android/modules/databinding-xstream/src/test/resources/ipo.xsd new file mode 100644 index 0000000000..aac7ded180 --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/test/resources/ipo.xsd @@ -0,0 +1,132 @@ +<!-- + * 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. +--> + +<schema targetNamespace="http://www.example.com/IPO" xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding-xstream/src/test/resources/order.wsdl b/branches/sca-android/modules/databinding-xstream/src/test/resources/order.wsdl new file mode 100644 index 0000000000..65da5b602a --- /dev/null +++ b/branches/sca-android/modules/databinding-xstream/src/test/resources/order.wsdl @@ -0,0 +1,76 @@ +<?xml version="1.0"?>
+<!--
+ * 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.
+-->
+<definitions name="StockQuote" targetNamespace="http://example.com/order.wsdl" xmlns:tns="http://example.com/order.wsdl"
+ xmlns:xsd1="http://example.com/order.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://schemas.xmlsoap.org/wsdl/">
+
+ <types>
+ <schema targetNamespace="http://example.com/order.xsd" xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+ <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd" />
+ <element name="checkOrderStatus">
+ <complexType>
+ <sequence>
+ <element name="customerId" type="string" />
+ <element name="order" type="ipo:PurchaseOrderType" />
+ <element name="flag" type="int" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="checkOrderStatusResponse">
+ <complexType>
+ <sequence>
+ <element name="status" type="string" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="note" type="string" />
+ </schema>
+ </types>
+
+ <message name="CheckOrderStatusInput1">
+ <part name="body" element="xsd1:checkOrderStatus" />
+ </message>
+
+ <message name="CheckOrderStatusOutput1">
+ <part name="body" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <message name="CheckOrderStatusInput2">
+ <part name="p1" element="xsd1:checkOrderStatus" />
+ <part name="p2" element="xsd1:note" />
+ </message>
+
+ <message name="CheckOrderStatusOutput2">
+ <part name="p1" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <portType name="OrderPortType">
+ <operation name="checkOrderStatus">
+ <input message="tns:CheckOrderStatusInput1" />
+ <output message="tns:CheckOrderStatusOutput1" />
+ </operation>
+ <operation name="checkOrderStatus2">
+ <input message="tns:CheckOrderStatusInput2" />
+ <output message="tns:CheckOrderStatusOutput2" />
+ </operation>
+ </portType>
+
+</definitions>
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding/LICENSE b/branches/sca-android/modules/databinding/LICENSE new file mode 100644 index 0000000000..616bec99ed --- /dev/null +++ b/branches/sca-android/modules/databinding/LICENSE @@ -0,0 +1,244 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + +----------------------------------------------------------------- +The test cases use xmlunit with the following license: +----------------------------------------------------------------- + +/* +****************************************************************** +Copyright (c) 2001-2007, Jeff Martin, Tim Bacon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +****************************************************************** +*/ + + diff --git a/branches/sca-android/modules/databinding/NOTICE b/branches/sca-android/modules/databinding/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/databinding/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/databinding/pom.xml b/branches/sca-android/modules/databinding/pom.xml new file mode 100644 index 0000000000..890abcc2ea --- /dev/null +++ b/branches/sca-android/modules/databinding/pom.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding</artifactId> + <name>Apache Tuscany SCA DataBinding Framework</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-extensibility</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-xsd</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-sca-api</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>javax.xml.stream</groupId> + <artifactId>stax-api</artifactId> + <version>1.0-2</version> + </dependency> + + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>wstx-asl</artifactId> + <version>3.2.1</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>xmlunit</groupId> + <artifactId>xmlunit</artifactId> + <version>1.1</version> + <scope>test</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.databinding</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.databinding*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java new file mode 100644 index 0000000000..547f9d9f4f --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java @@ -0,0 +1,104 @@ +/* + * 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.databinding; + + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * DataBinding represents a data representation, for example, SDO, JAXB and AXIOM + * + * @version $Rev$ $Date$ + */ +public interface DataBinding { + /** + * A special databinding for input message of an operation + */ + String IDL_INPUT = "idl:input"; + /** + * A special databinding for output message of an operation + */ + String IDL_OUTPUT = "idl:output"; + /** + * A special databinding for fault message of an operation + */ + String IDL_FAULT = "idl:fault"; + /** + * The name of a databinding should be case-insensitive and unique + * + * @return The name of the databinding + */ + String getName(); + + /** + * Get the aliases for the databinding + * + * @return An array of aliases + */ + String[] getAliases(); + + /** + * Introspect and populate information to a DataType model + * + * @param dataType The data type to be introspected + * @param operation The operation + * @return true if the databinding has recognized the given data type + */ + boolean introspect(DataType dataType, Operation operation); + + /** + * Introspect the data to figure out the corresponding data type + * + * @param value The object to be checked + * @param operation The operation + * @return The DataType or null if the java type is not supported by this databinding + */ + DataType introspect(Object value, Operation operation); + + /** + * Provide a WrapperHandler for this databinding + * @return A wrapper handler which can handle wrapping/wrapping for this databinding + */ + WrapperHandler getWrapperHandler(); + + /** + * Make a copy of the object for "pass-by-value" semantics. + * + * @param object source object to copy + * @param dataType The data type + * @param operation The operation + * @return copy of the object passed in as argument + */ + Object copy(Object object, DataType dataType, Operation operation); + + /** + * Get the type mapper for simple types + * @return The databinding-specific simple type mapper + */ + SimpleTypeMapper getSimpleTypeMapper(); + + /** + * Get the XML type helper for Java types + * @return The databinding-specific XML type helper class + */ + XMLTypeHelper getXMLTypeHelper(); + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBindingExtensionPoint.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBindingExtensionPoint.java new file mode 100644 index 0000000000..2ff5d866b4 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBindingExtensionPoint.java @@ -0,0 +1,74 @@ +/* + * 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.databinding; + + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * An extension point for data binding extensions. + * + * @version $Rev$ $Date$ + */ +public interface DataBindingExtensionPoint { + + /** + * Register a data binding + * + * @param dataBinding + */ + void addDataBinding(DataBinding dataBinding); + + /** + * Look up a data binding by id + * + * @param id The name of the databinding + * @return The databinding + */ + DataBinding getDataBinding(String id); + + /** + * Unregister a data binding + * + * @param id + * @return The unregistered databinding + */ + DataBinding removeDataBinding(String id); + + /** + * Introspect the java class to figure out what DataType supports it. + * + * @param dataType The initial data type + * @param operation TODO + * @return A DataType representing the java type or null if no databinding + * recognizes the java type + */ + boolean introspectType(DataType dataType, Operation operation); + + /** + * Introspect the value to figure out the corresponding DataType + * + * @param value The object value + * @param operation TODO + * @return A DataType representing the value or null if no databinding + * recognizes the value + */ + DataType introspectType(Object value, Operation operation); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipe.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipe.java new file mode 100644 index 0000000000..505a810276 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipe.java @@ -0,0 +1,46 @@ +/* + * 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.databinding; + +/** + * Data pipe allows a data source pushes data into its sink and pipe the data into its result + * + * @param <S> The data binding type of the sink + * @param <R> The data binding type of the result + * + * @version $Rev$ $Date$ + */ +public interface DataPipe<S, R> { + + /** + * Returns a sink (for example, java.io.OutputStream, java.io.Writer or org.xml.sax.ContentHandler) to receive data + * pushed by the source + * + * @return The sink to consume data + */ + S getSink(); + + /** + * Returns the data populated by the sink + * + * @return + */ + R getResult(); + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipeTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipeTransformer.java new file mode 100644 index 0000000000..1aac6d48be --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipeTransformer.java @@ -0,0 +1,29 @@ +/* + * 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.databinding; + +/** + * Data pipe allows a data source pushes data into its sink and pipe the data into its result + * + * @version $Rev$ $Date$ + */ +public interface DataPipeTransformer<S, R> extends Transformer { + + DataPipe<S, R> newInstance(); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java new file mode 100644 index 0000000000..b2da024a72 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java @@ -0,0 +1,268 @@ +/* + * 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.databinding; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; +import org.apache.tuscany.sca.databinding.javabeans.JavaExceptionDataBinding; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * The default implementation of a data binding extension point. + * + * @version $Rev$ $Date$ + */ +public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoint { + private final Map<String, DataBinding> bindings = new HashMap<String, DataBinding>(); + private final List<DataBinding> databindings = new ArrayList<DataBinding>(); + private static final Logger logger = Logger.getLogger(DefaultDataBindingExtensionPoint.class.getName()); + private boolean loadedDataBindings; + + public DefaultDataBindingExtensionPoint() { + } + + public DataBinding getDataBinding(String id) { + if (id == null) { + return null; + } + DataBinding dataBinding = bindings.get(id.toLowerCase()); + if (dataBinding == null) { + loadDataBindings(); + dataBinding = bindings.get(id.toLowerCase()); + } + return dataBinding; + } + + public void addDataBinding(DataBinding dataBinding) { + if (logger.isLoggable(Level.FINE)) { + String className = dataBinding.getClass().getName(); + boolean lazy = false; + if (dataBinding instanceof LazyDataBinding) { + className = ((LazyDataBinding)dataBinding).dataBindingDeclaration.getClassName(); + lazy = true; + } + logger.fine("Adding databinding: " + className + ";type=" + dataBinding.getName() + ",lazy=" + lazy); + } + databindings.add(dataBinding); + bindings.put(dataBinding.getName().toLowerCase(), dataBinding); + + String[] aliases = dataBinding.getAliases(); + if (aliases != null) { + for (String alias : aliases) { + bindings.put(alias.toLowerCase(), dataBinding); + } + } + } + + public DataBinding removeDataBinding(String id) { + if (id == null) { + return null; + } + DataBinding dataBinding = bindings.remove(id.toLowerCase()); + if (dataBinding != null) { + databindings.remove(dataBinding); + String[] aliases = dataBinding.getAliases(); + if (aliases != null) { + for (String alias : aliases) { + bindings.remove(alias.toLowerCase()); + } + } + } + return dataBinding; + } + + /** + * Dynamically load data bindings declared under META-INF/services + */ + private synchronized void loadDataBindings() { + if (loadedDataBindings) + return; + + // Get the databinding service declarations + Set<ServiceDeclaration> dataBindingDeclarations; + try { + dataBindingDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(DataBinding.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // Load data bindings + for (ServiceDeclaration dataBindingDeclaration : dataBindingDeclarations) { + Map<String, String> attributes = dataBindingDeclaration.getAttributes(); + String type = attributes.get("type"); + String name = attributes.get("name"); + + // Create a data binding wrapper and register it + DataBinding dataBinding = new LazyDataBinding(type, name, dataBindingDeclaration); + addDataBinding(dataBinding); + } + + loadedDataBindings = true; + } + + /** + * A data binding facade allowing data bindings to be lazily loaded and + * initialized. + */ + private static class LazyDataBinding implements DataBinding { + + private String name; + private String[] aliases; + private ServiceDeclaration dataBindingDeclaration; + private DataBinding dataBinding; + + private LazyDataBinding(String type, String name, ServiceDeclaration dataBindingDeclaration) { + this.name = type; + if (name != null) { + this.aliases = new String[] {name}; + } + this.dataBindingDeclaration = dataBindingDeclaration; + } + + /** + * Load and instantiate the data binding class. + * + * @return The data binding. + */ + @SuppressWarnings("unchecked") + private DataBinding getDataBinding() { + if (dataBinding == null) { + try { + Class<DataBinding> dataBindingClass = (Class<DataBinding>)dataBindingDeclaration.loadClass(); + Constructor<DataBinding> constructor = dataBindingClass.getConstructor(); + dataBinding = constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return dataBinding; + } + + public Object copy(Object object, DataType dataType, Operation operation) { + return getDataBinding().copy(object, dataType, operation); + } + + public String[] getAliases() { + return aliases; + } + + public String getName() { + return name; + } + + public SimpleTypeMapper getSimpleTypeMapper() { + return getDataBinding().getSimpleTypeMapper(); + } + + public XMLTypeHelper getXMLTypeHelper() { + return getDataBinding().getXMLTypeHelper(); + } + + public WrapperHandler getWrapperHandler() { + return getDataBinding().getWrapperHandler(); + } + + public boolean introspect(DataType dataType, Operation operation) { + return getDataBinding().introspect(dataType, operation); + } + + public DataType introspect(Object value, Operation operation) { + return getDataBinding().introspect(value, operation); + } + } + + //FIXME The following methods should not be on the extension point + // they should be on a separate class + public boolean introspectType(DataType dataType, Operation operation) { + loadDataBindings(); + for (DataBinding binding : databindings) { + // don't introspect for JavaBeansDatabinding as all javatypes will + // anyways match to its basetype + // which is java.lang.Object. Default to this only if no databinding + // results + if (!binding.getName().equals(JavaBeansDataBinding.NAME)) { + if (binding.introspect(dataType, operation)) { + return true; + } + } + } + // FIXME: Should we honor the databinding from operation/interface + // level? + Class physical = dataType.getPhysical(); + if (physical == Object.class) { + dataType.setDataBinding(JavaBeansDataBinding.NAME); + return false; + } + if (dataType.getPhysical().isArray()) { + introspectArray(dataType, operation); + return true; + } else if (Throwable.class.isAssignableFrom(physical)) { + dataType.setDataBinding(JavaExceptionDataBinding.NAME); + return true; + } else { + dataType.setDataBinding(JavaBeansDataBinding.NAME); + return false; + } + } + + private boolean introspectArray(DataType dataType, Operation operation) { + Class physical = dataType.getPhysical(); + if (!physical.isArray() || physical == byte[].class) { + return false; + } + Class componentType = physical.getComponentType(); + DataType logical = new DataTypeImpl(componentType, dataType.getLogical()); + introspectType(logical, operation); + dataType.setDataBinding("java:array"); + dataType.setLogical(logical); + return true; + } + + public DataType introspectType(Object value, Operation operation) { + loadDataBindings(); + DataType dataType = null; + for (DataBinding binding : databindings) { + // don't introspect for JavaBeansDatabinding as all javatypes will + // anyways match to its basetype + // which is java.lang.Object. Default to this only if no databinding + // results + if (!binding.getName().equals(JavaBeansDataBinding.NAME)) { + dataType = binding.introspect(value, operation); + } + if (dataType != null) { + return dataType; + } + } + return new DataTypeImpl<XMLType>(JavaBeansDataBinding.NAME, value.getClass(), XMLType.UNKNOWN); + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultTransformerExtensionPoint.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultTransformerExtensionPoint.java new file mode 100644 index 0000000000..2ab9471c91 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultTransformerExtensionPoint.java @@ -0,0 +1,305 @@ +/* + * 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.databinding; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.databinding.impl.DirectedGraph; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * @version $Rev$ $Date$ + */ +public class DefaultTransformerExtensionPoint implements TransformerExtensionPoint { + private static final Logger logger = Logger.getLogger(DefaultTransformerExtensionPoint.class.getName()); + private boolean loadedTransformers; + + private final DirectedGraph<Object, Transformer> graph = new DirectedGraph<Object, Transformer>(); + + public DefaultTransformerExtensionPoint() { + } + + public void addTransformer(String sourceType, String resultType, int weight, Transformer transformer, boolean publicTransformer) { + if (logger.isLoggable(Level.FINE)) { + String className = transformer.getClass().getName(); + boolean lazy = false; + boolean pull = (transformer instanceof PullTransformer); + if (transformer instanceof LazyPullTransformer) { + className = ((LazyPullTransformer)transformer).transformerDeclaration.getClassName(); + lazy = true; + } + if (transformer instanceof LazyPushTransformer) { + className = ((LazyPushTransformer)transformer).transformerDeclaration.getClassName(); + lazy = true; + } + + logger.fine("Adding transformer: " + className + + ";source=" + + sourceType + + ",target=" + + resultType + + ",weight=" + + weight + + ",type=" + + (pull ? "pull" : "push") + + ",lazy=" + + lazy); + } + graph.addEdge(sourceType, resultType, transformer, weight, publicTransformer); + } + + public void addTransformer(Transformer transformer, boolean publicTransformer) { + addTransformer(transformer.getSourceDataBinding(), + transformer.getTargetDataBinding(), + transformer.getWeight(), + transformer, publicTransformer); + } + + public boolean removeTransformer(String sourceType, String resultType) { + return graph.removeEdge(sourceType, resultType); + } + + public Transformer getTransformer(String sourceType, String resultType) { + loadTransformers(); + + DirectedGraph<Object, Transformer>.Edge edge = graph.getEdge(sourceType, resultType); + return (edge == null) ? null : edge.getValue(); + } + + /** + * Dynamically load transformers registered under META-INF/services. + * + */ + private void loadTransformers() { + if (loadedTransformers) { + return; + } + loadTransformers(PullTransformer.class); + loadTransformers(PushTransformer.class); + loadedTransformers = true; + } + + /** + * Dynamically load transformers registered under META-INF/services. + * + * @param transformerClass + */ + private void loadTransformers(Class<?> transformerClass) { + + // Get the transformer service declarations + Set<ServiceDeclaration> transformerDeclarations; + + try { + transformerDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(transformerClass); + + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // Load transformers + for (ServiceDeclaration transformerDeclaration : transformerDeclarations) { + Map<String, String> attributes = transformerDeclaration.getAttributes(); + + String source = attributes.get("source"); + String target = attributes.get("target"); + int weight = Integer.valueOf(attributes.get("weight")); + String b = attributes.get("public"); + boolean pub = true; + if (b != null) { + pub = Boolean.valueOf(b); + } + + // Create a transformer wrapper and register it + Transformer transformer; + if (transformerClass == PullTransformer.class) { + transformer = new LazyPullTransformer(source, target, weight, transformerDeclaration); + } else { + transformer = new LazyPushTransformer(source, target, weight, transformerDeclaration); + } + addTransformer(transformer, pub); + } + } + + /** + * A transformer facade allowing transformers to be lazily loaded + * and initialized. + */ + private static class LazyPullTransformer implements PullTransformer<Object, Object> { + + private String source; + private String target; + private int weight; + private ServiceDeclaration transformerDeclaration; + private PullTransformer<Object, Object> transformer; + + public LazyPullTransformer(String source, String target, int weight, ServiceDeclaration transformerDeclaration) { + this.source = source; + this.target = target; + this.weight = weight; + this.transformerDeclaration = transformerDeclaration; + } + + /** + * Load and instantiate the transformer class. + * + * @return The transformer. + */ + @SuppressWarnings("unchecked") + private PullTransformer<Object, Object> getTransformer() { + if (transformer == null) { + try { + Class<PullTransformer<Object, Object>> transformerClass = + (Class<PullTransformer<Object, Object>>)transformerDeclaration.loadClass(); + Constructor<PullTransformer<Object, Object>> constructor = transformerClass.getConstructor(); + transformer = constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return transformer; + } + + public String getSourceDataBinding() { + return source; + } + + public String getTargetDataBinding() { + return target; + } + + public int getWeight() { + return weight; + } + + public Object transform(Object source, TransformationContext context) { + return getTransformer().transform(source, context); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(super.toString()); + sb.append(";className=").append(transformerDeclaration.getClassName()); + return sb.toString(); + } + } + + /** + * A transformer facade allowing transformers to be lazily loaded + * and initialized. + */ + private static class LazyPushTransformer implements PushTransformer<Object, Object> { + + private String source; + private String target; + private int weight; + private ServiceDeclaration transformerDeclaration; + private PushTransformer<Object, Object> transformer; + + public LazyPushTransformer(String source, String target, int weight, ServiceDeclaration transformerDeclaration) { + this.source = source; + this.target = target; + this.weight = weight; + this.transformerDeclaration = transformerDeclaration; + } + + /** + * Load and instantiate the transformer class. + * + * @return The transformer. + */ + @SuppressWarnings("unchecked") + private PushTransformer<Object, Object> getTransformer() { + if (transformer == null) { + try { + Class<PushTransformer<Object, Object>> transformerClass = + (Class<PushTransformer<Object, Object>>)transformerDeclaration.loadClass(); + Constructor<PushTransformer<Object, Object>> constructor = transformerClass.getConstructor(); + transformer = constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return transformer; + } + + public String getSourceDataBinding() { + return source; + } + + public String getTargetDataBinding() { + return target; + } + + public int getWeight() { + return weight; + } + + public void transform(Object source, Object sink, TransformationContext context) { + getTransformer().transform(source, sink, context); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(super.toString()); + sb.append(";className=").append(transformerDeclaration.getClassName()); + return sb.toString(); + } + } + + //FIXME The following methods should be on a different class from + // extension point + + public List<Transformer> getTransformerChain(String sourceType, String resultType) { + loadTransformers(); + + String source = sourceType; + String result = resultType; + List<Transformer> transformers = new ArrayList<Transformer>(); + // First check if there is a direct path, if yes, use it regardless of the weight + DirectedGraph<Object, Transformer>.Edge link = graph.getEdge(sourceType, resultType); + if (link != null) { + transformers.add(link.getValue()); + } else { + DirectedGraph<Object, Transformer>.Path path = graph.getShortestPath(source, result); + if (path == null) { + return null; + } + for (DirectedGraph<Object, Transformer>.Edge edge : path.getEdges()) { + transformers.add(edge.getValue()); + } + } + return transformers; + } + + @Override + public String toString() { + loadTransformers(); + + return graph.toString(); + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java new file mode 100644 index 0000000000..6b8acfc7b4 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java @@ -0,0 +1,68 @@ +/* + * 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.databinding; + +import java.util.Map; + +import org.apache.tuscany.sca.interfacedef.DataType; + +/** + * This interface will be used as a Tuscany system service to perform data mediations + * + * Mediate the data from one type to the other one + * + * @version $Rev$ $Date$ + */ +public interface Mediator { + + /** + * Mediate the data from the source type to the target type + * @param source The data to be mediated + * @param sourceDataType Data type for the source data + * @param targetDataType Data type for the target data + * @param context + * @return + */ + Object mediate(Object source, DataType sourceDataType, DataType targetDataType, Map<String, Object> context); + /** + * Mediate the source data into the target which is a sink to receive the data + * @param source The data to be mediated + * @param target The sink to receive data + * @param sourceDataType Data type for the source data + * @param targetDataType Data type for the target data + */ + void mediate( + Object source, + Object target, + DataType sourceDataType, + DataType targetDataType, + Map<String, Object> context); + + /** + * Get the DataBindings used by this mediator. + * @return + */ + DataBindingExtensionPoint getDataBindings(); + + /** + * Get the Transformers used by this mediator. + * @return + */ + TransformerExtensionPoint getTransformers(); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PullTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PullTransformer.java new file mode 100644 index 0000000000..81264923eb --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PullTransformer.java @@ -0,0 +1,38 @@ +/* + * 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.databinding; + +/** + * PullTransformer transforms data from one binding format to the other one which can be directly consumed + * + * @param <S> The source data type + * @param <R> the target data type + * + * @version $Rev$ $Date$ + */ +public interface PullTransformer<S, R> extends Transformer { + /** + * Transform source data into the result type. + * + * @param source The source data + * @param context The context for the transformation + * @return The transformed result + */ + R transform(S source, TransformationContext context); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PushTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PushTransformer.java new file mode 100644 index 0000000000..600a6477f6 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PushTransformer.java @@ -0,0 +1,36 @@ +/* + * 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.databinding; + +/** + * A transformer that pushes data from its source into the sink + * + * @param <S> + * @param <R> + * + * @version $Rev$ $Date$ + */ +public interface PushTransformer<S, R> extends Transformer { + /** + * @param source The source data + * @param sink The sink to receive the data + * @param context + */ + void transform(S source, R sink, TransformationContext context); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/SimpleTypeMapper.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/SimpleTypeMapper.java new file mode 100644 index 0000000000..4e6d130aa9 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/SimpleTypeMapper.java @@ -0,0 +1,46 @@ +/* + * 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.databinding; + +import javax.xml.namespace.QName; + +/** + * Type Mapper between XML schema simple data types and java objects + * + * @version $Rev$ $Date$ + */ +public interface SimpleTypeMapper { + /** + * Parse the XML lexical representation into a java object + * @param simpleType The XSD simple type + * @param value the XML lexical representation + * @param context The context of the transformation + * @return A java object for the XML value + */ + Object toJavaObject(QName simpleType, String value, TransformationContext context); + /** + * Create the XML lexical representation for a java object + * @param simpleType The XSD simple type + * @param obj The java object + * @param context The context of the transformation + * @return The XML lexical representation + */ + String toXMLLiteral(QName simpleType, Object obj, TransformationContext context); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationContext.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationContext.java new file mode 100644 index 0000000000..9ffadd1eae --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationContext.java @@ -0,0 +1,95 @@ +/* + * 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.databinding; + +import java.util.Map; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * Context for data transformation + * + * @version $Rev$ $Date$ + */ +public interface TransformationContext { + + /** + * @return + */ + Operation getSourceOperation(); + + /** + * @param sourceOperation + */ + void setSourceOperation(Operation sourceOperation); + + /** + * @return + */ + Operation getTargetOperation(); + + /** + * @param targetOperation + */ + void setTargetOperation(Operation targetOperation); + + /** + * Get the source data type + * + * @return + */ + DataType getSourceDataType(); + + /** + * Get the target data type + * + * @return + */ + DataType getTargetDataType(); + + /** + * Set the source data type + * + * @param sourceDataType + */ + void setSourceDataType(DataType sourceDataType); + + /** + * Set the target data type + * + * @param targetDataType + */ + void setTargetDataType(DataType targetDataType); + + /** + * Get the ClassLoader + * + * @return Returns the ClassLoader + */ + ClassLoader getClassLoader(); + + /** + * Get a map of metadata + * + * @return Returns a map of the metadata + */ + Map<String, Object> getMetadata(); + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationException.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationException.java new file mode 100644 index 0000000000..4f949f7dff --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationException.java @@ -0,0 +1,65 @@ +/* + * 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.databinding; + + +/** + * Reports problems during data transformation + * + * @version $Rev$ $Date$ + */ +public class TransformationException extends RuntimeException { + + private static final long serialVersionUID = 7662385613693006428L; + private String sourceDataBinding; + private String targetDataBinding; + + public TransformationException() { + super(); + } + + public TransformationException(String message, Throwable cause) { + super(message, cause); + } + + public TransformationException(String message) { + super(message); + } + + public TransformationException(Throwable cause) { + super(cause); + } + + public String getSourceDataBinding() { + return sourceDataBinding; + } + + public void setSourceDataBinding(String sourceDataBinding) { + this.sourceDataBinding = sourceDataBinding; + } + + public String getTargetDataBinding() { + return targetDataBinding; + } + + public void setTargetDataBinding(String targetDataBinding) { + this.targetDataBinding = targetDataBinding; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Transformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Transformer.java new file mode 100644 index 0000000000..2aa0ad7c15 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Transformer.java @@ -0,0 +1,51 @@ +/* + * 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.databinding; + +/** + * A transformer provides the data transformation from source type to target type. The cost of the transformation is + * modelled as weight. + * + * @version $Rev$ $Date$ + */ +public interface Transformer { + /** + * Get the source type that this transformer transforms data from. The type is used as the key when the transformer + * is registered with TransformerRegistry. + * + * @return A key identifying the source type + */ + String getSourceDataBinding(); + + /** + * Get the target type that this transformer transforms data into. The type is used as the key when the transformer + * is registered with TransformerRegistry. + * + * @return A key identifying the target type + */ + String getTargetDataBinding(); + + /** + * Get the cost of the transformation. The weight can be used to choose the most efficient path if there are more + * than one available from the source to the target. + * + * @return An integer representing the cost of the transformation + */ + int getWeight(); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformerExtensionPoint.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformerExtensionPoint.java new file mode 100644 index 0000000000..ee7efe4860 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformerExtensionPoint.java @@ -0,0 +1,81 @@ +/* + * 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.databinding; + +import java.util.List; + +/** + * An extension point for data transformer extensions. + * + * @version $Rev$ $Date$ + */ +public interface TransformerExtensionPoint { + + /** + * Register a transformer + * + * @param sourceDataBinding + * @param targetDataBinding + * @param weight + * @param transformer + * @param publicTransformer TODO + */ + void addTransformer(String sourceDataBinding, + String targetDataBinding, + int weight, + Transformer transformer, + boolean publicTransformer); + + /** + * Register a transformer + * + * @param transformer + * @param publicTransformer TODO + */ + void addTransformer(Transformer transformer, boolean publicTransformer); + + /** + * Unregister a transformer + * + * @param sourceDataBinding + * @param targetDataBinding + * @return + */ + boolean removeTransformer(String sourceDataBinding, String targetDataBinding); + + /** + * Get the direct Transformer which can transform data from source type to + * result type + * + * @param sourceDataBinding + * @param targetDataBinding + * @return + */ + Transformer getTransformer(String sourceDataBinding, String targetDataBinding); + + /** + * Get the a chain of Transformers which can transform data from source type + * to result type + * + * @param sourceDataBinding + * @param targetDataBinding + * @return + */ + List<Transformer> getTransformerChain(String sourceDataBinding, String targetDataBinding); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/WrapperHandler.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/WrapperHandler.java new file mode 100644 index 0000000000..a91410ed71 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/WrapperHandler.java @@ -0,0 +1,78 @@ +/* + * 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.databinding; + +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * A contract for transformers to deal with wrapping/unwrapping for WSDL wrapper style operations + * + * @version $Rev$ $Date$ + */ +public interface WrapperHandler<T> { + /** + * Create a wrapper element + * @param operation The operation + * @param input Is it for input or output + * @return An object representing the wrapper element + */ + T create(Operation operation, boolean input); + + /** + * Get the data type for the wrapper + * @param operation The operation + * @param input Is it for input or output? + * @return The data type of the wrapper, null if it's not a wrapper type + */ + DataType getWrapperType(Operation operation, boolean input); + + /** + * Check if the given data is an instance of the wrapper + * @param wrapper + * @param operation The operation + * @param input Input or output + * @return + */ + boolean isInstance(Object wrapper, Operation operation, boolean input); + + /** + * Populate the wrapper element with the child objects + * @param wrapper The wrapper object + * @param childObjects The child objects + * @param operation The operation + * @param input Is it for input or output + */ + public void setChildren(T wrapper, + Object[] childObjects, + Operation operation, + boolean input); + + /** + * Get a list of child elements from the wrapper + * @param wrapper The wrapper object + * @param operation The operation + * @param input Is it for input or output + * @return child elements under the wrapper + */ + List getChildren(T wrapper, Operation operation, boolean input); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/XMLTypeHelper.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/XMLTypeHelper.java new file mode 100644 index 0000000000..e940f8675f --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/XMLTypeHelper.java @@ -0,0 +1,68 @@ +/* + * 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.databinding; + +import java.util.List; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.xsd.XSDFactory; +import org.apache.tuscany.sca.xsd.XSDefinition; + +/** + * XML and schema helper for Java types + */ +public interface XMLTypeHelper { + + // FIXME: This method seems to require the XMLHelper instance to be stateful + /** + * Convert a Java type into XML type information + * @param javaType the physical Java class + * @param logical the logical type information + * @return the XML type information + */ + TypeInfo getTypeInfo(Class javaType, Object logical); + + /** + * Get schema definitions for the Java types known to this helper + * @return A list of schema definitions + */ + // List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver); + + /** + * Get a list of XML schemas for the given data types + * @param factory + * @param resolver + * @param dataTypes + * @return + */ + List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, List<DataType> dataTypes); + /** + * Get a list of XML schemas for the given interface + * @param factory + * @param resolver + * @param intf + * @return + */ + List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, Interface intf); + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataBinding.java new file mode 100644 index 0000000000..4405077e29 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataBinding.java @@ -0,0 +1,56 @@ +/* + * 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.databinding.annotation; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Used to demarcate the mapping style for an interface or operation + * + * @version $Rev$ $Date$ + */ +// FIXME: [rfeng] We should consider to use javax.jws.soap.SOAPBinding +@Target({TYPE, METHOD}) +@Retention(RUNTIME) +public @interface DataBinding { + + /** + * Indicate the effective databinding that controls the WSDL/Java mapping of the + * interface/operation + * + * @return the data binding with the MIME media type syntax + */ + String value(); + + /** + * Indicate if the operation is mapped using WRAPPED or BARE style. Originated from + * javax.jws.soap.SOAPBinding.ParameterStyle: Determines whether method parameters + * represent the entire message body, or whether the parameters are elements wrapped + * inside a top-level element named after the operation + * + * @return true if the parameter style is WRAPPED, false if BARE + */ + boolean wrapped() default false; + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataType.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataType.java new file mode 100644 index 0000000000..650e909c61 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataType.java @@ -0,0 +1,43 @@ +/* + * 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.databinding.annotation; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Used to demarcate expected data types for parameters and return type + * + * @version $Rev$ $Date$ + */ +@Target( {METHOD, PARAMETER}) +@Retention(RUNTIME) +public @interface DataType { + + /** + * Returns the data binding configuration in MIME media type syntax + * @return the data binding + */ + String value(); + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/externalizable/ExternalizableDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/externalizable/ExternalizableDataBinding.java new file mode 100644 index 0000000000..640a43f55d --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/externalizable/ExternalizableDataBinding.java @@ -0,0 +1,40 @@ +/*
+ * 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.databinding.externalizable;
+
+import org.apache.tuscany.sca.databinding.impl.BaseDataBinding;
+
+/**
+ * DataNinding for Externalizable objects.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExternalizableDataBinding extends BaseDataBinding {
+
+ public static final String NAME = java.io.Externalizable.class.getName();
+ public static final String[] ALIASES = new String[] {"externalizable"};
+
+ public ExternalizableDataBinding() {
+ super(NAME, ALIASES, java.io.Externalizable.class);
+ }
+
+
+
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java new file mode 100644 index 0000000000..4bbcf7ddef --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java @@ -0,0 +1,133 @@ +/* + * 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.databinding.impl; + + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Base Implementation of DataBinding + * + * @version $Rev$ $Date$ + */ +public abstract class BaseDataBinding implements DataBinding { + + private Class<?> baseType; + + private String name; + private String[] aliases; + + /** + * Create a databinding with the base java type whose name will be used as + * the name of the databinding + * + * @param baseType The base java class or interface representing the + * databinding, for example, org.w3c.dom.Node + */ + protected BaseDataBinding(Class<?> baseType) { + this(baseType.getName(), null, baseType); + } + + /** + * Create a databinding with the name and base java type + * + * @param name The name of the databinding + * @param baseType The base java class or interface representing the + * databinding, for example, org.w3c.dom.Node + */ + protected BaseDataBinding(String name, Class<?> baseType) { + this(name, null, baseType); + } + + /** + * Create a databinding with the name and base java type + * + * @param name The name of the databinding + * @param aliases The aliases of the databinding + * @param baseType The base java class or interface representing the + * databinding, for example, org.w3c.dom.Node + */ + protected BaseDataBinding(String name, String[] aliases, Class<?> baseType) { + this.name = name; + this.baseType = baseType; + this.aliases = aliases; + } + + @SuppressWarnings("unchecked") + public boolean introspect(DataType type, Operation operation) { + assert type != null; + Class cls = type.getPhysical(); + if (baseType != null && baseType.isAssignableFrom(cls)) { + type.setDataBinding(getName()); + if (type.getLogical() == null) { + type.setLogical(XMLType.UNKNOWN); + } + return true; + } + return false; + } + + public DataType introspect(Object value, Operation operation) { + if (value == null) { + return null; + } else { + DataType<Class> dataType = new DataTypeImpl<Class>(value.getClass(), value.getClass()); + if (introspect(dataType, (Operation) null)) { + return dataType; + } else { + return null; + } + } + } + + public final String getName() { + return name; + } + + /** + * @see org.apache.tuscany.sca.databinding.DataBinding#getWrapperHandler() + */ + public WrapperHandler getWrapperHandler() { + return null; + } + + public Object copy(Object object, DataType dataType, Operation operation) { + return object; + } + + public SimpleTypeMapper getSimpleTypeMapper() { + return new SimpleTypeMapperImpl(); + } + + public XMLTypeHelper getXMLTypeHelper() { + return null; + } + + public String[] getAliases() { + return aliases; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseTransformer.java new file mode 100644 index 0000000000..94a2cdb0bb --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseTransformer.java @@ -0,0 +1,52 @@ +/* + * 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.databinding.impl; + +import org.apache.tuscany.sca.databinding.Transformer; + +/** + * Base Implementation of Transformer which provides the registration to the + * transformer registry + * + * @version $Rev$ $Date$ + */ +public abstract class BaseTransformer<S, T> implements Transformer { + + protected BaseTransformer() { + super(); + } + + protected abstract Class<S> getSourceType(); + + protected abstract Class<T> getTargetType(); + + public String getSourceDataBinding() { + return getSourceType().getName(); + } + + public String getTargetDataBinding() { + return getTargetType().getName(); + } + + public int getWeight() { + // default to 50 + return 50; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/DOMHelper.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/DOMHelper.java new file mode 100644 index 0000000000..64b3d22c10 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/DOMHelper.java @@ -0,0 +1,163 @@ +/* + * 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.databinding.impl; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +/** + * Helper for DOM + * + * @version $Rev$ $Date$ + */ +public final class DOMHelper { + private static DocumentBuilderFactory FACTORY; + + private DOMHelper() { + } + + public static Document newDocument() throws ParserConfigurationException { + return newDocumentBuilder().newDocument(); + } + + public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + init(); + return FACTORY.newDocumentBuilder(); + } + + /** + * + */ + private static synchronized void init() { + if (FACTORY == null) { + FACTORY = DocumentBuilderFactory.newInstance(); + FACTORY.setNamespaceAware(true); + } + } + + public static QName getQName(Node node) { + String ns = node.getNamespaceURI(); + if (ns == null) { + ns = ""; + } + // node.getLocalName() will return null if it is created using DOM Level + // 1 method + // such as createElement() + return new QName(ns, node.getNodeName()); + } + + public static Element createElement(Document document, QName name) { + String prefix = name.getPrefix(); + String qname = + (prefix != null && prefix.length() > 0) ? prefix + ":" + name.getLocalPart() : name.getLocalPart(); + return document.createElementNS(name.getNamespaceURI(), qname); + } + + /** + * Wrap an element as a DOM document + * @param node + * @return + */ + public static Document promote(Node node) { + if (node instanceof Document) { + return (Document)node; + } + Element element = (Element)node; + Document doc = element.getOwnerDocument(); + if (doc.getDocumentElement() == element) { + return doc; + } + doc = (Document)element.getOwnerDocument().cloneNode(false); + Element schema = (Element)doc.importNode(element, true); + doc.appendChild(schema); + Node parent = element.getParentNode(); + while (parent instanceof Element) { + Element root = (Element)parent; + NamedNodeMap nodeMap = root.getAttributes(); + for (int i = 0; i < nodeMap.getLength(); i++) { + Attr attr = (Attr)nodeMap.item(i); + String name = attr.getName(); + if ("xmlns".equals(name) || name.startsWith("xmlns:")) { + if (schema.getAttributeNode(name) == null) { + schema.setAttributeNodeNS((Attr)doc.importNode(attr, true)); + } + } + } + parent = parent.getParentNode(); + } + return doc; + } + + /** + * @param context + * @param element + */ + public static Element adjustElementName(TransformationContext context, Element element) { + if (context != null) { + DataType dataType = context.getTargetDataType(); + Object logical = dataType == null ? null : dataType.getLogical(); + if (!(logical instanceof XMLType)) { + return element; + } + XMLType xmlType = (XMLType)logical; + QName name = new QName(element.getNamespaceURI(), element.getLocalName()); + if (xmlType.isElement() && !xmlType.getElementName().equals(name)) { + QName newName = xmlType.getElementName(); + String prefix = newName.getPrefix(); + String qname = newName.getLocalPart(); + if (prefix != null && !prefix.equals("")) { + qname = prefix + ":" + qname; + } + Document doc = element.getOwnerDocument(); + Element newElement = doc.createElementNS(newName.getNamespaceURI(), qname); + // Copy the attributes to the new element + NamedNodeMap attrs = element.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + Attr attr = (Attr)doc.importNode(attrs.item(i), true); + newElement.getAttributes().setNamedItem(attr); + } + + // Move all the children + while (element.hasChildNodes()) { + newElement.appendChild(element.getFirstChild()); + } + + // Replace the old node with the new node + if (element.getParentNode() != null) { + element.getParentNode().replaceChild(newElement, element); + } + + return newElement; + } + } + return element; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/DirectedGraph.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/DirectedGraph.java new file mode 100644 index 0000000000..01916dfb96 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/DirectedGraph.java @@ -0,0 +1,452 @@ +/* + * 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.databinding.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Directed, weighted graph + * + * @param <V> The type of vertex object + * @param <E> The type of edge object + * + * @version $Rev$ $Date$ + */ +public class DirectedGraph<V, E> implements Cloneable { + private final Map<V, Vertex> vertices = new HashMap<V, Vertex>(); + + /** + * Key for the shortest path cache + */ + private final class VertexPair { + private Vertex source; + + private Vertex target; + + /** + * @param source + * @param target + */ + private VertexPair(Vertex source, Vertex target) { + super(); + this.source = source; + this.target = target; + } + + @Override + public boolean equals(Object object) { + if (!VertexPair.class.isInstance(object)) { + return false; + } + VertexPair pair = (VertexPair)object; + return source == pair.source && target == pair.target; + } + + @Override + public int hashCode() { + int x = source == null ? 0 : source.hashCode(); + int y = target == null ? 0 : target.hashCode(); + return x ^ y; + } + + } + + // Fix for TUSCANY-2069, making the map concurrent + private final Map<VertexPair, Path> paths = new ConcurrentHashMap<VertexPair, Path>(); + private final Path NULL_PATH = new Path(); + + /** + * Vertex of a graph + */ + public final class Vertex { + private V value; + + // TODO: Do we want to support multiple edges for a vertex pair? If so, + // we should use a List instead of Map + private Map<Vertex, Edge> outEdges = new HashMap<Vertex, Edge>(); + private Map<Vertex, Edge> inEdges = new HashMap<Vertex, Edge>(); + + private Vertex(V value) { + this.value = value; + } + + @Override + public String toString() { + return "(" + value + ")"; + } + + public V getValue() { + return value; + } + + public Map<Vertex, Edge> getOutEdges() { + return outEdges; + } + + public Map<Vertex, Edge> getInEdges() { + return inEdges; + } + + } + + /** + * An Edge connects two vertices in one direction + */ + public final class Edge { + private Vertex sourceVertex; + + private Vertex targetVertex; + + private E value; + + private int weight; + + private boolean pub = true; + + public Edge(Vertex source, Vertex target, E value, int weight, boolean pub) { + this.sourceVertex = source; + this.targetVertex = target; + this.value = value; + this.weight = weight; + this.pub = pub; + } + + @Override + public String toString() { + return sourceVertex + "->" + targetVertex + "[" + value + "," + weight + "]"; + } + + public E getValue() { + return value; + } + + public void setValue(E value) { + this.value = value; + } + + public Vertex getTargetVertex() { + return targetVertex; + } + + public void setTargetVertex(Vertex vertex) { + this.targetVertex = vertex; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public Vertex getSourceVertex() { + return sourceVertex; + } + + public void setSourceVertex(Vertex sourceVertex) { + this.sourceVertex = sourceVertex; + } + + public boolean isPublic() { + return pub; + } + + public void setPublic(boolean pub) { + this.pub = pub; + } + } + + private final class Node implements Comparable<Node> { + + private long distance = Integer.MAX_VALUE; + + private Node previous; // NOPMD by rfeng on 9/26/06 9:17 PM + + private Vertex vertex; // NOPMD by rfeng on 9/26/06 9:17 PM + + private Node(Vertex vertex) { + this.vertex = vertex; + } + + public int compareTo(Node o) { + return (distance > o.distance) ? 1 : ((distance == o.distance) ? 0 : -1); + } + } + + public void addEdge(V source, V target, E edgeValue, int weight, boolean publicEdge) { + Vertex s = getVertex(source); + if (s == null) { + s = new Vertex(source); + vertices.put(source, s); + } + Vertex t = getVertex(target); + if (t == null) { + t = new Vertex(target); + vertices.put(target, t); + } + Edge edge = new Edge(s, t, edgeValue, weight, publicEdge); + s.outEdges.put(t, edge); + t.inEdges.put(s, edge); + } + + public void addEdge(V soure, V target) { + addEdge(soure, target, null, 0, true); + } + + public Vertex getVertex(V source) { + Vertex s = vertices.get(source); + return s; + } + + public boolean removeEdge(V source, V target) { + Vertex s = getVertex(source); + if (s == null) { + return false; + } + + Vertex t = getVertex(target); + if (t == null) { + return false; + } + + return s.outEdges.remove(t) != null && t.inEdges.remove(s) != null; + + } + + public void removeEdge(Edge edge) { + edge.sourceVertex.outEdges.remove(edge.targetVertex); + edge.targetVertex.inEdges.remove(edge.sourceVertex); + } + + public void removeVertex(Vertex vertex) { + vertices.remove(vertex.getValue()); + for (Edge e : new ArrayList<Edge>(vertex.outEdges.values())) { + removeEdge(e); + } + for (Edge e : new ArrayList<Edge>(vertex.inEdges.values())) { + removeEdge(e); + } + } + + public Edge getEdge(Vertex source, Vertex target) { + return source.outEdges.get(target); + } + + public Edge getEdge(V source, V target) { + Vertex sv = getVertex(source); + if (sv == null) { + return null; + } + Vertex tv = getVertex(target); + if (tv == null) { + return null; + } + return getEdge(getVertex(source), getVertex(target)); + } + + /** + * Get the shortest path from the source vertex to the target vertex using + * Dijkstra's algorithm. If there's no path, null will be returned. If the + * source is the same as the target, it returns a path with empty edges with + * weight 0. + * + * @param sourceValue The value identifies the source + * @param targetValue The value identifies the target + * @return The shortest path + */ + public Path getShortestPath(V sourceValue, V targetValue) { + Vertex source = getVertex(sourceValue); + if (source == null) { + return null; + } + Vertex target = getVertex(targetValue); + if (target == null) { + return null; + } + + VertexPair pair = new VertexPair(source, target); + Path path = null; + if (paths.containsKey(pair)) { + path = paths.get(pair); + return path == NULL_PATH? null: path; + } + + // Check if there is a direct link, if yes, use it instead + Edge direct = getEdge(source, target); + path = new Path(); + if (direct != null) { + path.addEdge(direct); + paths.put(pair, path); + return path; + } + + Map<Vertex, Node> nodes = new HashMap<Vertex, Node>(); + for (Vertex v : vertices.values()) { + Node node = new Node(v); + if (v == source) { + node.distance = 0; + } + nodes.put(v, node); + } + + Set<Node> otherNodes = new HashSet<Node>(nodes.values()); + Set<Node> nodesOnPath = new HashSet<Node>(); + Node nextNode = null; + while (!otherNodes.isEmpty()) { + nextNode = extractMin(otherNodes); + if (nextNode.vertex == target) { + path = getPath(nextNode); + paths.put(pair, path); // Cache it + return path == NULL_PATH? null: path; + } + nodesOnPath.add(nextNode); + for (Edge edge : nextNode.vertex.outEdges.values()) { + Node adjacentNode = nodes.get(edge.targetVertex); + // The private edge can only be used if the edge connects to the target directly + if (edge.isPublic() || edge.getTargetVertex() == target) { + if (nextNode.distance + edge.weight < adjacentNode.distance) { + adjacentNode.distance = nextNode.distance + edge.weight; + adjacentNode.previous = nextNode; + } + } + } + } + paths.put(pair, NULL_PATH); // Cache it + return null; + } + + /** + * Searches for the vertex u in the vertex set Q that has the least d[u] + * value. That vertex is removed from the set Q and returned to the user. + * + * @param nodes + * @return + */ + private Node extractMin(Set<Node> nodes) { + Node node = Collections.min(nodes); + nodes.remove(node); + return node; + } + + /** + * The path between two vertices + */ + public final class Path { + private List<Edge> edges = new LinkedList<Edge>(); + + private int weight; + + public int getWeight() { + return weight; + } + + public List<Edge> getEdges() { + return edges; + } + + public void addEdge(Edge edge) { + edges.add(0, edge); + weight += edge.weight; + } + + @Override + public String toString() { + return edges + ", " + weight; + } + } + + private Path getPath(Node t) { + if (t.distance == Integer.MAX_VALUE) { + return NULL_PATH; + } + Path path = new Path(); + Node u = t; + while (u.previous != null) { + Edge edge = getEdge(u.previous.vertex, u.vertex); + path.addEdge(edge); + u = u.previous; + } + return path; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for (Vertex v : vertices.values()) { + sb.append(v.outEdges.values()).append("\n"); + } + return sb.toString(); + } + + public Map<V, Vertex> getVertices() { + return vertices; + } + + public void addGraph(DirectedGraph<V, E> otherGraph) { + for (Vertex v : otherGraph.vertices.values()) { + for (Edge e : v.outEdges.values()) { + addEdge(e.sourceVertex.value, e.targetVertex.value, e.value, e.weight, true); + } + } + } + + private Vertex getFirst() { + for (Vertex v : vertices.values()) { + if (v.inEdges.isEmpty()) { + return v; + } + } + if (!vertices.isEmpty()) { + throw new IllegalArgumentException("Circular ordering has been detected: " + toString()); + } else { + return null; + } + } + + public List<V> topologicalSort(boolean readOnly) { + DirectedGraph<V, E> graph = (!readOnly) ? this : (DirectedGraph<V, E>)clone(); + List<V> list = new ArrayList<V>(); + while (true) { + Vertex v = graph.getFirst(); + if (v == null) { + break; + } + list.add(v.getValue()); + graph.removeVertex(v); + } + + return list; + } + + @Override + public Object clone() { + DirectedGraph<V, E> copy = new DirectedGraph<V, E>(); + copy.addGraph(this); + return copy; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Group2GroupTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Group2GroupTransformer.java new file mode 100644 index 0000000000..cc7b40d06b --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Group2GroupTransformer.java @@ -0,0 +1,94 @@ +/* + * 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.databinding.impl; + +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.interfacedef.DataType; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + * + * @version $Rev$ $Date$ + */ +public class Group2GroupTransformer extends BaseTransformer<Object, Object> implements + PullTransformer<Object, Object> { + + protected Mediator mediator; + + /** + * @param wrapperHandler + */ + public Group2GroupTransformer() { + super(); + } + + /** + * @param mediator the mediator to set + */ + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + @Override + public String getSourceDataBinding() { + return GroupDataBinding.NAME; + } + + @Override + public String getTargetDataBinding() { + return GroupDataBinding.NAME; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getSourceType() + */ + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getTargetType() + */ + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10; + } + + @SuppressWarnings("unchecked") + public Object transform(Object source, TransformationContext context) { + DataType<DataType> sourceType = context.getSourceDataType(); + DataType<DataType> targetType = context.getTargetDataType(); + + return mediator.mediate(source, sourceType.getLogical(), targetType.getLogical(), context.getMetadata()); + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/GroupDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/GroupDataBinding.java new file mode 100644 index 0000000000..4a918488c5 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/GroupDataBinding.java @@ -0,0 +1,103 @@ +/* + * 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.databinding.impl; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * The base class for a special databinding which represents a group of other databindings + * + * @version $Rev$ $Date$ + */ +public abstract class GroupDataBinding extends BaseDataBinding { + public static final String NAME = "databinding:group"; + + /** + * Marker type is a java class or interface representing the data format. + */ + protected Class[] markerTypes; + + public GroupDataBinding(Class[] types) { + super(NAME, null, GroupDataBinding.class); + this.markerTypes = types; + } + + @SuppressWarnings("unchecked") + @Override + public boolean introspect(DataType type, Operation operation) { + if (markerTypes == null) { + return false; + } + Type physical = type.getPhysical(); + if (physical instanceof ParameterizedType) { + physical = ((ParameterizedType)physical).getRawType(); + } + if (!(physical instanceof Class)) { + return false; + } + Class cls = (Class)physical; + for (Class<?> c : markerTypes) { + if (isTypeOf(c, cls)) { + type.setDataBinding(getDataBinding(c)); + Object logical = getLogical(cls, null); + if (logical != null) { + type.setLogical(getLogical(cls, null)); + } else { + type.setLogical(XMLType.UNKNOWN); + } + return true; + } + } + return false; + } + + /** + * Test if the given type is a subtype of the base type + * @param markerType + * @param type + * @return + */ + protected boolean isTypeOf(Class<?> markerType, Class<?> type) { + return markerType.isAssignableFrom(type); + } + + /** + * Derive the databinding name from a base class + * @param baseType + * @return + */ + protected String getDataBinding(Class<?> baseType) { + return baseType.getName(); + } + + /** + * Get the logical type + * @param type The java type + * @param operation TODO + * @return + */ + protected abstract Object getLogical(Class<?> type, Operation operation); + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Java2SimpleTypeTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Java2SimpleTypeTransformer.java new file mode 100644 index 0000000000..45896ca6a1 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Java2SimpleTypeTransformer.java @@ -0,0 +1,70 @@ +/* + * 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.databinding.impl; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Transformer to convert data from a simple java object to a databinding's representation + * + * @version $Rev$ $Date$ + */ +public abstract class Java2SimpleTypeTransformer<T> extends BaseTransformer<Object, T> implements + PullTransformer<Object, T> { + + protected SimpleTypeMapper mapper; + + public Java2SimpleTypeTransformer() { + this.mapper = new SimpleTypeMapperImpl(); + } + + public Java2SimpleTypeTransformer(SimpleTypeMapper mapper) { + this.mapper = (mapper != null) ? mapper : new SimpleTypeMapperImpl(); + } + + public T transform(Object source, TransformationContext context) { + XMLType xmlType = (XMLType) context.getTargetDataType().getLogical(); + String text = mapper.toXMLLiteral(xmlType.getTypeName(), source, context); + return createElement(xmlType.getElementName(), text, context); + } + + @Override + public Class<Object> getSourceType() { + return Object.class; + } + + @Override + public int getWeight() { + return 10000; + } + + protected abstract T createElement(QName element, String literal, TransformationContext context); + + @Override + public String getSourceDataBinding() { + return SimpleJavaDataBinding.NAME; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java new file mode 100644 index 0000000000..b7ddf87a41 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java @@ -0,0 +1,182 @@ +/* + * 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.databinding.impl; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.Transformer; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; + +/** + * Default Mediator implementation + * + * @version $Rev$ $Date$ + */ +public class MediatorImpl implements Mediator { + + private DataBindingExtensionPoint dataBindings; + private TransformerExtensionPoint transformers; + + public MediatorImpl(DataBindingExtensionPoint dataBindings, TransformerExtensionPoint transformers) { + this.dataBindings = dataBindings; + this.transformers = transformers; + } + + @SuppressWarnings("unchecked") + public Object mediate(Object source, DataType sourceDataType, DataType targetDataType, Map<String, Object> metadata) { + if (sourceDataType == null || sourceDataType.getDataBinding() == null) { + if (source != null) { + Operation operation = (Operation) metadata.get("source.operation"); + sourceDataType = dataBindings.introspectType(source, operation); + } + } + if (sourceDataType == null || targetDataType == null) { + return source; + } else if (sourceDataType.equals(targetDataType)) { + return source; + } + + List<Transformer> path = getTransformerChain(sourceDataType, targetDataType); + + Object result = source; + int size = path.size(); + int i = 0; + while (i < size) { + Transformer transformer = path.get(i); + TransformationContext context = + createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata); + // the source and target type + if (transformer instanceof PullTransformer) { + // For intermediate node, set data type to null + result = ((PullTransformer)transformer).transform(result, context); + } else if (transformer instanceof PushTransformer) { + DataPipeTransformer dataPipeFactory = (i < size - 1) ? (DataPipeTransformer)path.get(++i) : null; + DataPipe dataPipe = dataPipeFactory == null ? null : dataPipeFactory.newInstance(); + ((PushTransformer)transformer).transform(result, dataPipe.getSink(), context); + result = dataPipe.getResult(); + } + i++; + } + + return result; + } + + private TransformationContext createTransformationContext(DataType sourceDataType, + DataType targetDataType, + int size, + int index, + Transformer transformer, + Map<String, Object> metadata) { + DataType sourceType = + (index == 0) ? sourceDataType : new DataTypeImpl<Object>(transformer.getSourceDataBinding(), Object.class, + sourceDataType.getLogical()); + DataType targetType = + (index == size - 1) ? targetDataType : new DataTypeImpl<Object>(transformer.getTargetDataBinding(), + Object.class, targetDataType.getLogical()); + + //FIXME The ClassLoader should be passed in + // Allow privileged access to get ClassLoader. Requires RuntimePermission in security + // policy. + ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + + TransformationContext context = new TransformationContextImpl(sourceType, targetType, classLoader, metadata); + return context; + } + + @SuppressWarnings("unchecked") + public void mediate(Object source, + Object target, + DataType sourceDataType, + DataType targetDataType, + Map<String, Object> metadata) { + if (source == null) { + // Shortcut for null value + return; + } + if (sourceDataType == null || sourceDataType.getDataBinding() == null) { + Operation operation = (Operation) metadata.get("source.operation"); + sourceDataType = dataBindings.introspectType(source, operation); + } + if (sourceDataType == null) { + return; + } else if (sourceDataType.equals(targetDataType)) { + return; + } + + List<Transformer> path = getTransformerChain(sourceDataType, targetDataType); + Object result = source; + int size = path.size(); + for (int i = 0; i < size; i++) { + Transformer transformer = path.get(i); + TransformationContext context = + createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata); + + if (transformer instanceof PullTransformer) { + result = ((PullTransformer)transformer).transform(result, context); + } else if (transformer instanceof PushTransformer) { + DataPipeTransformer dataPipeFactory = (i < size - 1) ? (DataPipeTransformer)path.get(++i) : null; + DataPipe dataPipe = dataPipeFactory == null ? null : dataPipeFactory.newInstance(); + Object sink = dataPipe != null ? dataPipe.getSink() : target; + ((PushTransformer)transformer).transform(result, sink, context); + result = (dataPipe != null) ? dataPipe.getResult() : null; + } + } + } + + private List<Transformer> getTransformerChain(DataType sourceDataType, DataType targetDataType) { + String sourceId = sourceDataType.getDataBinding(); + String targetId = targetDataType.getDataBinding(); + List<Transformer> path = transformers.getTransformerChain(sourceId, targetId); + if (path == null) { + TransformationException ex = + new TransformationException("No path found for the transformation: " + sourceId + "->" + targetId); + ex.setSourceDataBinding(sourceId); + ex.setTargetDataBinding(targetId); + throw ex; + } + return path; + } + + public DataBindingExtensionPoint getDataBindings() { + return dataBindings; + } + + public TransformerExtensionPoint getTransformers() { + return transformers; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/PipedTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/PipedTransformer.java new file mode 100644 index 0000000000..a1a89005b3 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/PipedTransformer.java @@ -0,0 +1,70 @@ +/* + * 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.databinding.impl; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; + +/** + * A utility class to connect PushTransformer and DataPipe to create a + * PullTransformer + * + * @param <S> Source type + * @param <I> Intermediate type + * @param <R> Result type + * + * @version $Rev$ $Date$ + */ +public class PipedTransformer<S, I, R> implements PullTransformer<S, R> { + private PushTransformer<S, I> pusher; + + private DataPipeTransformer<I, R> pipe; + + /** + * @param pumper + * @param pipe + */ + public PipedTransformer(PushTransformer<S, I> pumper, DataPipeTransformer<I, R> pipe) { + super(); + this.pusher = pumper; + this.pipe = pipe; + } + + public R transform(S source, TransformationContext context) { + DataPipe<I, R> dataPipe = pipe.newInstance(); + pusher.transform(source, dataPipe.getSink(), context); + return dataPipe.getResult(); + } + + public String getSourceDataBinding() { + return pusher.getSourceDataBinding(); + } + + public String getTargetDataBinding() { + return pipe.getTargetDataBinding(); + } + + public int getWeight() { + return pusher.getWeight() + pipe.getWeight(); + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleType2JavaTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleType2JavaTransformer.java new file mode 100644 index 0000000000..c91176fc2c --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleType2JavaTransformer.java @@ -0,0 +1,89 @@ +/* + * 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.databinding.impl; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Transformer to convert data from a databinding's representation of simple + * types to Java Objects + * + * @version $Rev$ $Date$ + */ +public abstract class SimpleType2JavaTransformer<T> extends BaseTransformer<T, Object> implements + PullTransformer<T, Object> { + + protected SimpleTypeMapper mapper; + + public SimpleType2JavaTransformer() { + this.mapper = new SimpleTypeMapperImpl(); + } + + public SimpleType2JavaTransformer(SimpleTypeMapper mapper) { + this.mapper = (mapper != null) ? mapper : new SimpleTypeMapperImpl(); + } + + public Object transform(T source, TransformationContext context) { + XMLType xmlType = (XMLType)context.getSourceDataType().getLogical(); + QName type = (xmlType != null) ? xmlType.getTypeName() : null; + if (type == null) { + xmlType = (XMLType)context.getTargetDataType().getLogical(); + type = (xmlType != null) ? xmlType.getTypeName() : null; + } + Object result = mapper.toJavaObject(type, getText(source), context); + close(source); + return result; + } + + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + @Override + public int getWeight() { + // Cannot be used for intermediate + return 10000; + } + + /** + * Get the string value from the source + * @param source + * @return A string + */ + protected abstract String getText(T source); + + /** + * To be overrided by the subclass + * @param source + */ + protected void close(T source) { + } + + @Override + public String getTargetDataBinding() { + return SimpleJavaDataBinding.NAME; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleTypeMapperImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleTypeMapperImpl.java new file mode 100644 index 0000000000..32a2313f59 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleTypeMapperImpl.java @@ -0,0 +1,401 @@ +/* + * 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.databinding.impl; + +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; + +/** + * Simple type mapper that maps from XSD types to Java Classes and Java Classes to XSD types. + * + * @version $Rev$ $Date$ + */ +public class SimpleTypeMapperImpl extends XSDDataTypeConverter implements SimpleTypeMapper { + + public static final Map<Class, String> JAVA2XML = new HashMap<Class, String>(); + + public static final String URI_2001_SCHEMA_XSD = "http://www.w3.org/2001/XMLSchema"; + + public static final Map<String, Class> XML2JAVA = new HashMap<String, Class>(); + + public static final QName XSD_ANY = new QName(URI_2001_SCHEMA_XSD, "any"); + + public static final QName XSD_ANYSIMPLETYPE = new QName(URI_2001_SCHEMA_XSD, "anySimpleType"); + + public static final QName XSD_ANYTYPE = new QName(URI_2001_SCHEMA_XSD, "anyType"); + + public static final QName XSD_ANYURI = new QName(URI_2001_SCHEMA_XSD, "anyURI"); + + public static final QName XSD_BASE64 = new QName(URI_2001_SCHEMA_XSD, "base64Binary"); + + public static final QName XSD_BOOLEAN = new QName(URI_2001_SCHEMA_XSD, "boolean"); + + public static final QName XSD_BYTE = new QName(URI_2001_SCHEMA_XSD, "byte"); + + public static final QName XSD_DATE = new QName(URI_2001_SCHEMA_XSD, "date"); + + public static final QName XSD_DATETIME = new QName(URI_2001_SCHEMA_XSD, "dateTime"); + + public static final QName XSD_DAY = new QName(URI_2001_SCHEMA_XSD, "gDay"); + + public static final QName XSD_DECIMAL = new QName(URI_2001_SCHEMA_XSD, "decimal"); + + public static final QName XSD_DOUBLE = new QName(URI_2001_SCHEMA_XSD, "double"); + + public static final QName XSD_DURATION = new QName(URI_2001_SCHEMA_XSD, "duration"); + + public static final QName XSD_ENTITIES = new QName(URI_2001_SCHEMA_XSD, "ENTITIES"); + + public static final QName XSD_ENTITY = new QName(URI_2001_SCHEMA_XSD, "ENTITY"); + + public static final QName XSD_FLOAT = new QName(URI_2001_SCHEMA_XSD, "float"); + + public static final QName XSD_HEXBIN = new QName(URI_2001_SCHEMA_XSD, "hexBinary"); + + public static final QName XSD_IDREF = new QName(URI_2001_SCHEMA_XSD, "IDREF"); + + public static final QName XSD_IDREFS = new QName(URI_2001_SCHEMA_XSD, "IDREFS"); + + public static final QName XSD_INT = new QName(URI_2001_SCHEMA_XSD, "int"); + + public static final QName XSD_INTEGER = new QName(URI_2001_SCHEMA_XSD, "integer"); + + public static final QName XSD_LONG = new QName(URI_2001_SCHEMA_XSD, "long"); + + public static final QName XSD_MONTH = new QName(URI_2001_SCHEMA_XSD, "gMonth"); + + public static final QName XSD_MONTHDAY = new QName(URI_2001_SCHEMA_XSD, "gMonthDay"); + + public static final QName XSD_NAME = new QName(URI_2001_SCHEMA_XSD, "Name"); + + public static final QName XSD_NCNAME = new QName(URI_2001_SCHEMA_XSD, "NCName"); + + public static final QName XSD_NEGATIVEINTEGER = new QName(URI_2001_SCHEMA_XSD, "negativeInteger"); + + public static final QName XSD_NMTOKEN = new QName(URI_2001_SCHEMA_XSD, "NMTOKEN"); + + public static final QName XSD_NMTOKENS = new QName(URI_2001_SCHEMA_XSD, "NMTOKENS"); + + public static final QName XSD_NONNEGATIVEINTEGER = new QName(URI_2001_SCHEMA_XSD, "nonNegativeInteger"); + + public static final QName XSD_NONPOSITIVEINTEGER = new QName(URI_2001_SCHEMA_XSD, "nonPositiveInteger"); + + public static final QName XSD_NORMALIZEDSTRING = new QName(URI_2001_SCHEMA_XSD, "normalizedString"); + + public static final QName XSD_NOTATION = new QName(URI_2001_SCHEMA_XSD, "NOTATION"); + + public static final QName XSD_POSITIVEINTEGER = new QName(URI_2001_SCHEMA_XSD, "positiveInteger"); + + public static final QName XSD_QNAME = new QName(URI_2001_SCHEMA_XSD, "QName"); + + public static final QName XSD_SHORT = new QName(URI_2001_SCHEMA_XSD, "short"); + + public static final Map<String, TypeInfo> XSD_SIMPLE_TYPES = new HashMap<String, TypeInfo>(); + + public static final QName XSD_STRING = new QName(URI_2001_SCHEMA_XSD, "string"); + + public static final QName XSD_TIME = new QName(URI_2001_SCHEMA_XSD, "time"); + + public static final QName XSD_TOKEN = new QName(URI_2001_SCHEMA_XSD, "token"); + + public static final QName XSD_UNSIGNEDBYTE = new QName(URI_2001_SCHEMA_XSD, "unsignedByte"); + + public static final QName XSD_UNSIGNEDINT = new QName(URI_2001_SCHEMA_XSD, "unsignedInt"); + + public static final QName XSD_UNSIGNEDLONG = new QName(URI_2001_SCHEMA_XSD, "unsignedLong"); + + public static final QName XSD_UNSIGNEDSHORT = new QName(URI_2001_SCHEMA_XSD, "unsignedShort"); + + public static final QName XSD_YEAR = new QName(URI_2001_SCHEMA_XSD, "gYear"); + + public static final QName XSD_YEARMONTH = new QName(URI_2001_SCHEMA_XSD, "gYearMonth"); + + private static final String[] XSD_TYPE_NAMES = + {"string", "boolean", "double", "float", "int", "integer", "long", "short", "byte", "decimal", "base64Binary", + "hexBinary", "anySimpleType", "anyType", "any", "QName", "dateTime", "date", "time", "normalizedString", + "token", "unsignedLong", "unsignedInt", "unsignedShort", "unsignedByte", "positiveInteger", "negativeInteger", + "nonNegativeInteger", "nonPositiveInteger", "gYearMonth", "gMonthDay", "gYear", "gMonth", "gDay", "duration", + "Name", "NCName", "NMTOKEN", "NMTOKENS", "NOTATION", "ENTITY", "ENTITIES", "IDREF", "IDREFS", "anyURI", + "language", "ID"}; + + static { + for (String type : XSD_TYPE_NAMES) { + TypeInfo simpleType = new TypeInfo(new QName(URI_2001_SCHEMA_XSD, type), true, null); + XSD_SIMPLE_TYPES.put(type, simpleType); + } + } + + static { + JAVA2XML.put(boolean.class, "boolean"); + JAVA2XML.put(byte.class, "byte"); + JAVA2XML.put(short.class, "short"); + JAVA2XML.put(int.class, "int"); + JAVA2XML.put(long.class, "long"); + JAVA2XML.put(float.class, "float"); + JAVA2XML.put(double.class, "double"); + JAVA2XML.put(Boolean.class, "boolean"); + JAVA2XML.put(Byte.class, "byte"); + JAVA2XML.put(Short.class, "short"); + JAVA2XML.put(Integer.class, "int"); + JAVA2XML.put(Long.class, "long"); + JAVA2XML.put(Float.class, "float"); + JAVA2XML.put(Double.class, "double"); + JAVA2XML.put(java.lang.String.class, "string"); + JAVA2XML.put(java.math.BigInteger.class, "integer"); + JAVA2XML.put(java.math.BigDecimal.class, "decimal"); + JAVA2XML.put(java.util.Calendar.class, "dateTime"); + JAVA2XML.put(java.util.Date.class, "dateTime"); + JAVA2XML.put(javax.xml.namespace.QName.class, "QName"); + JAVA2XML.put(java.net.URI.class, "string"); + JAVA2XML.put(javax.xml.datatype.XMLGregorianCalendar.class, "anySimpleType"); + JAVA2XML.put(javax.xml.datatype.Duration.class, "duration"); + JAVA2XML.put(java.lang.Object.class, "anyType"); + JAVA2XML.put(java.awt.Image.class, "base64Binary"); + JAVA2XML.put(byte[].class, "base64Binary"); + // java2XSD.put(javax.activation.DataHandler.class, "base64Binary"); + JAVA2XML.put(javax.xml.transform.Source.class, "base64Binary"); + JAVA2XML.put(java.util.UUID.class, "string"); + } + + static { + XML2JAVA.put("string", java.lang.String.class); + XML2JAVA.put("integer", java.math.BigInteger.class); + XML2JAVA.put("int", int.class); + XML2JAVA.put("long", long.class); + XML2JAVA.put("short", short.class); + XML2JAVA.put("decimal", java.math.BigDecimal.class); + XML2JAVA.put("float", float.class); + XML2JAVA.put("double", double.class); + XML2JAVA.put("boolean", boolean.class); + XML2JAVA.put("byte", byte.class); + XML2JAVA.put("QName", javax.xml.namespace.QName.class); + XML2JAVA.put("dateTime", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("base64Binary", byte[].class); + XML2JAVA.put("hexBinary", byte[].class); + XML2JAVA.put("unsignedInt", long.class); + XML2JAVA.put("unsignedShort", int.class); + XML2JAVA.put("unsignedByte", short.class); + XML2JAVA.put("time", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("date", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gDay", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gMonth", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gYear", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gYearMonth", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gMonthDay", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("anySimpleType", java.lang.Object.class); // For elements + // XML2JAVA.put("anySimpleType", java.lang.String.class); // For + // attributes + XML2JAVA.put("duration", javax.xml.datatype.Duration.class); + XML2JAVA.put("NOTATION", javax.xml.namespace.QName.class); + } + + private DatatypeFactory factory; + + public SimpleTypeMapperImpl() { + super(); + try { + this.factory = DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new IllegalArgumentException(e); + } + } + + public static Class getJavaType(QName xmlType) { + if (xmlType != null && URI_2001_SCHEMA_XSD.equals(xmlType.getNamespaceURI())) { + return XML2JAVA.get(xmlType.getLocalPart()); + } else { + return null; + } + } + + public static TypeInfo getXMLType(Class javaType) { + return XSD_SIMPLE_TYPES.get(JAVA2XML.get(javaType)); + } + + public Object toJavaObject(QName simpleType, String literal, TransformationContext context) { + /** + * <ul> + * <li>xsd:string --- java.lang.String + * <li>xsd:integer --- java.math.BigInteger + * <li>xsd:int --- int + * <li>xsd:long --- long + * <li>xsd:short --- short + * <li>xsd:decimal --- java.math.BigDecimal + * <li>xsd:float --- float + * <li>xsd:double --- double + * <li>xsd:boolean --- boolean + * <li>xsd:byte --- byte + * <li>xsd:QName --- javax.xml.namespace.QName + * <li>xsd:dateTime --- javax.xml.datatype.XMLGregorianCalendar + * <li>xsd:base64Binary --- byte[] + * <li>xsd:hexBinary --- byte[] + * <li>xsd:unsignedInt --- long + * <li>xsd:unsignedShort --- int + * <li>xsd:unsignedByte --- short + * <li>xsd:time --- javax.xml.datatype.XMLGregorianCalendar + * <li>xsd:date --- javax.xml.datatype.XMLGregorianCalendar + * <li>xsd:g* --- javax.xml.datatype.XMLGregorianCalendar + * <li>xsd:anySimpleType (for xsd:element of this type)a + * java.lang.Object + * <li>xsd:anySimpleType (for xsd:attribute of this type) + * java.lang.String + * <li>xsd:duration javax.xml.datatype.Duration + * <li>xsd:NOTATION javax.xml.namespace.QName + * </ul> + */ + + if (literal == null) { + return null; + } + String value = literal.trim(); + + QName type = simpleType; + if (type.equals(XSD_STRING)) { + return parseString(value); + } else if (type.equals(XSD_INT)) { + return parseInt(value); + } else if (type.equals(XSD_INTEGER)) { + return parseInteger(value); + } else if (type.equals(XSD_INT)) { + return parseInt(value); + } else if (type.equals(XSD_FLOAT)) { + return parseFloat(value); + } else if (type.equals(XSD_DOUBLE)) { + return parseDouble(value); + } else if (type.equals(XSD_SHORT)) { + return parseShort(value); + } else if (type.equals(XSD_DECIMAL)) { + return parseDecimal(value); + } else if (type.equals(XSD_BOOLEAN)) { + return parseBoolean(value); + } else if (type.equals(XSD_BYTE)) { + return parseByte(value); + } else if (type.equals(XSD_LONG)) { + return parseLong(value); + } else if (type.equals(XSD_UNSIGNEDBYTE)) { + return parseUnsignedShort(value); + } else if (type.equals(XSD_UNSIGNEDSHORT)) { + return parseUnsignedShort(value); + } else if (type.equals(XSD_UNSIGNEDINT)) { + return parseUnsignedInt(value); + } else if (type.equals(XSD_UNSIGNEDLONG)) { + return parseUnsignedInt(value); + } else if (type.equals(XSD_DATETIME)) { + return parseDateTime(value); + } else if (type.equals(XSD_DATE)) { + return parseDate(value); + } else if (type.equals(XSD_TIME)) { + return parseTime(value); + } else if (type.equals(XSD_DURATION)) { + return parseDuration(value); + } else if (type.equals(XSD_HEXBIN)) { + return parseHexBinary(value); + } else if (type.equals(XSD_BASE64)) { + return parseBase64Binary(value); + } else if (type.equals(XSD_QNAME)) { + NamespaceContext namespaceContext = + (NamespaceContext)((context != null) ? context.getMetadata().get(NamespaceContext.class.getName()) : null); + return parseQName(value, namespaceContext); + } else if (type.equals(XSD_NOTATION)) { + NamespaceContext namespaceContext = + (NamespaceContext)((context != null) ? context.getMetadata().get(NamespaceContext.class.getName()) : null); + return parseQName(value, namespaceContext); + } else if (type.equals(XSD_YEAR)) { + return factory.newXMLGregorianCalendar(value); + } else if (type.equals(XSD_MONTH)) { + return factory.newXMLGregorianCalendar(value); + } else if (type.equals(XSD_DAY)) { + return factory.newXMLGregorianCalendar(value); + } else if (type.equals(XSD_YEARMONTH)) { + return factory.newXMLGregorianCalendar(value); + } else if (type.equals(XSD_MONTHDAY)) { + return factory.newXMLGregorianCalendar(value); + } else { + return value; + } + } + + @SuppressWarnings("deprecation") + private XMLGregorianCalendar toXMLGregorianCalendar(Date date) { + GregorianCalendar c = + new GregorianCalendar(date.getYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), + date.getSeconds()); + return factory.newXMLGregorianCalendar(c); + } + + private XMLGregorianCalendar toXMLGregorianCalendar(GregorianCalendar calendar) { + return factory.newXMLGregorianCalendar(calendar); + } + + public String toXMLLiteral(QName simpleType, Object obj, TransformationContext context) { + if(obj == null) { + // It could be null if nilable=true + return null; + } + if (obj instanceof Float || obj instanceof Double) { + if (obj instanceof Float) { + return printDouble(((Float)obj).floatValue()); + } else { + return printDouble(((Double)obj).doubleValue()); + } + } else if (obj instanceof GregorianCalendar) { + GregorianCalendar calendar = (GregorianCalendar)obj; + return toXMLGregorianCalendar(calendar).toXMLFormat(); + } else if (obj instanceof Date) { + return toXMLGregorianCalendar((Date)obj).toXMLFormat(); + } else if (obj instanceof XMLGregorianCalendar) { + return ((XMLGregorianCalendar)obj).toXMLFormat(); + } else if (obj instanceof byte[]) { + if (simpleType != null) { + if (simpleType.equals(XSD_BASE64)) { + return printBase64Binary((byte[])obj); + } else if (simpleType.equals(XSD_HEXBIN)) { + return printHexBinary((byte[])obj); + } + } + } else if (obj instanceof QName) { + NamespaceContext namespaceContext = + (NamespaceContext)((context != null) ? context.getMetadata().get(NamespaceContext.class.getName()) : null); + return printQName((QName)obj, namespaceContext); + } + return obj.toString(); + } + + public static boolean isSimpleXSDType(QName typeName) { + if (typeName == null) { + return false; + } + return typeName.getNamespaceURI().equals(URI_2001_SCHEMA_XSD) + && XSD_SIMPLE_TYPES.get(typeName.getLocalPart()) != null; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java new file mode 100644 index 0000000000..a6c0639411 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java @@ -0,0 +1,113 @@ +/* + * 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.databinding.impl; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +public class TransformationContextImpl implements TransformationContext { + private DataType sourceDataType; + + private DataType targetDataType; + + private final Map<String, Object> metadata = new HashMap<String, Object>(); + + private WeakReference<ClassLoader> classLoaderRef; + + public TransformationContextImpl() { + super(); + // This is used only for testing + setClassLoader(Thread.currentThread().getContextClassLoader()); + } + + public TransformationContextImpl(DataType sourceDataType, + DataType targetDataType, + ClassLoader classLoader, + Map<String, Object> metadata) { + super(); + this.sourceDataType = sourceDataType; + this.targetDataType = targetDataType; + setClassLoader(classLoader); + if (metadata != null) { + this.metadata.putAll(metadata); + } + } + + public DataType getSourceDataType() { + return sourceDataType; + } + + public DataType getTargetDataType() { + return targetDataType; + } + + public void setSourceDataType(DataType sourceDataType) { + this.sourceDataType = sourceDataType; + } + + public void setTargetDataType(DataType targetDataType) { + this.targetDataType = targetDataType; + } + + public final void setClassLoader(ClassLoader classLoader) { + this.classLoaderRef = new WeakReference<ClassLoader>(classLoader); + } + + public ClassLoader getClassLoader() { + return classLoaderRef.get(); + } + + public Map<String, Object> getMetadata() { + return metadata; + } + + /** + * @return the sourceOperation + */ + public Operation getSourceOperation() { + return (Operation) metadata.get("source.operation"); + } + + /** + * @param sourceOperation the sourceOperation to set + */ + public void setSourceOperation(Operation sourceOperation) { + this.metadata.put("source.operation", sourceOperation); + } + + /** + * @return the targetOperation + */ + public Operation getTargetOperation() { + return (Operation) metadata.get("target.operation"); + } + + /** + * @param targetOperation the targetOperation to set + */ + public void setTargetOperation(Operation targetOperation) { + this.metadata.put("target.operation", targetOperation); + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/XSDDataTypeConverter.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/XSDDataTypeConverter.java new file mode 100644 index 0000000000..fb747864e7 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/XSDDataTypeConverter.java @@ -0,0 +1,945 @@ +/* + * 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.databinding.impl; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.FieldPosition; +import java.text.Format; +import java.text.ParsePosition; +import java.util.Calendar; +import java.util.TimeZone; + +import javax.xml.XMLConstants; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.Duration; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; + +/** + * Utility class for XSD data type conversions + * + * @version $Rev$ $Date$ + */ +public class XSDDataTypeConverter { + public static final class Base64Binary { + private static final char[] S_BASE64CHAR = + {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', '+', '/'}; + + private static final char S_BASE64PAD = '='; + + private static final byte[] S_DECODETABLE = new byte[128]; + + static { + for (int i = 0; i < S_DECODETABLE.length; i++) { + S_DECODETABLE[i] = Byte.MAX_VALUE; // 127 + } + for (int i = 0; i < S_BASE64CHAR.length; i++) { + // 0 to 63 + S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i; + } + } + + private Base64Binary() { + } + + /** + * + */ + public static byte[] decode(char[] data, int off, int len) { + char[] ibuf = new char[4]; + int ibufcount = 0; + byte[] obuf = new byte[len / 4 * 3 + 3]; + int obufcount = 0; + for (int i = off; i < off + len; i++) { + char ch = data[i]; + if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { + ibuf[ibufcount++] = ch; + if (ibufcount == ibuf.length) { + ibufcount = 0; + obufcount += decode0(ibuf, obuf, obufcount); + } + } + } + if (obufcount == obuf.length) { + return obuf; + } + byte[] ret = new byte[obufcount]; + System.arraycopy(obuf, 0, ret, 0, obufcount); + return ret; + } + + /** + * + */ + public static void decode(char[] data, int off, int len, OutputStream ostream) throws IOException { + char[] ibuf = new char[4]; + int ibufcount = 0; + byte[] obuf = new byte[3]; + for (int i = off; i < off + len; i++) { + char ch = data[i]; + if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { + ibuf[ibufcount++] = ch; + if (ibufcount == ibuf.length) { + ibufcount = 0; + int obufcount = decode0(ibuf, obuf, 0); + ostream.write(obuf, 0, obufcount); + } + } + } + } + + /** + * + */ + public static byte[] decode(String data) { + char[] ibuf = new char[4]; + int ibufcount = 0; + byte[] obuf = new byte[data.length() / 4 * 3 + 3]; + int obufcount = 0; + for (int i = 0; i < data.length(); i++) { + char ch = data.charAt(i); + if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { + ibuf[ibufcount++] = ch; + if (ibufcount == ibuf.length) { + ibufcount = 0; + obufcount += decode0(ibuf, obuf, obufcount); + } + } + } + if (obufcount == obuf.length) { + return obuf; + } + byte[] ret = new byte[obufcount]; + System.arraycopy(obuf, 0, ret, 0, obufcount); + return ret; + } + + /** + * + */ + public static void decode(String data, OutputStream ostream) throws IOException { + char[] ibuf = new char[4]; + int ibufcount = 0; + byte[] obuf = new byte[3]; + for (int i = 0; i < data.length(); i++) { + char ch = data.charAt(i); + if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { + ibuf[ibufcount++] = ch; + if (ibufcount == ibuf.length) { + ibufcount = 0; + int obufcount = decode0(ibuf, obuf, 0); + ostream.write(obuf, 0, obufcount); + } + } + } + } + + private static int decode0(char[] ibuf, byte[] obuf, int index) { + int wp = index; + int outlen = 3; + if (ibuf[3] == S_BASE64PAD) { + outlen = 2; + } + if (ibuf[2] == S_BASE64PAD) { + outlen = 1; + } + int b0 = S_DECODETABLE[ibuf[0]]; + int b1 = S_DECODETABLE[ibuf[1]]; + int b2 = S_DECODETABLE[ibuf[2]]; + int b3 = S_DECODETABLE[ibuf[3]]; + switch (outlen) { + case 1: + obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); + return 1; + case 2: + obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); + obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); + return 2; + case 3: + obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); + obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); + obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f); + return 3; + default: + throw new IllegalArgumentException("The character sequence is not base64 encoded."); + } + } + + /** + * Returns base64 representation of specified byte array. + */ + public static String encode(byte[] data) { + return encode(data, 0, data.length); + } + + /** + * Returns base64 representation of specified byte array. + */ + public static String encode(byte[] data, int off, int len) { + if (len <= 0) { + return ""; + } + char[] out = new char[len / 3 * 4 + 4]; + int rindex = off; + int windex = 0; + int rest = len - off; + while (rest >= 3) { + int i = + ((data[rindex] & 0xff) << 16) + ((data[rindex + 1] & 0xff) << 8) + + (data[rindex + 2] & 0xff); + out[windex++] = S_BASE64CHAR[i >> 18]; + out[windex++] = S_BASE64CHAR[(i >> 12) & 0x3f]; + out[windex++] = S_BASE64CHAR[(i >> 6) & 0x3f]; + out[windex++] = S_BASE64CHAR[i & 0x3f]; + rindex += 3; + rest -= 3; + } + if (rest == 1) { + int i = data[rindex] & 0xff; + out[windex++] = S_BASE64CHAR[i >> 2]; + out[windex++] = S_BASE64CHAR[(i << 4) & 0x3f]; + out[windex++] = S_BASE64PAD; + out[windex++] = S_BASE64PAD; + } else if (rest == 2) { + int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); + out[windex++] = S_BASE64CHAR[i >> 10]; + out[windex++] = S_BASE64CHAR[(i >> 4) & 0x3f]; + out[windex++] = S_BASE64CHAR[(i << 2) & 0x3f]; + out[windex++] = S_BASE64PAD; + } + return new String(out, 0, windex); + } + + /** + * Outputs base64 representation of the specified byte array to a byte stream. + */ + public static void encode(byte[] data, int off, int len, OutputStream ostream) throws IOException { + if (len <= 0) { + return; + } + byte[] out = new byte[4]; + int rindex = off; + int rest = len - off; + while (rest >= 3) { + int i = + ((data[rindex] & 0xff) << 16) + ((data[rindex + 1] & 0xff) << 8) + + (data[rindex + 2] & 0xff); + out[0] = (byte) S_BASE64CHAR[i >> 18]; + out[1] = (byte) S_BASE64CHAR[(i >> 12) & 0x3f]; + out[2] = (byte) S_BASE64CHAR[(i >> 6) & 0x3f]; + out[3] = (byte) S_BASE64CHAR[i & 0x3f]; + ostream.write(out, 0, 4); + rindex += 3; + rest -= 3; + } + if (rest == 1) { + int i = data[rindex] & 0xff; + out[0] = (byte) S_BASE64CHAR[i >> 2]; + out[1] = (byte) S_BASE64CHAR[(i << 4) & 0x3f]; + out[2] = (byte) S_BASE64PAD; + out[3] = (byte) S_BASE64PAD; + ostream.write(out, 0, 4); + } else if (rest == 2) { + int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); + out[0] = (byte) S_BASE64CHAR[i >> 10]; + out[1] = (byte) S_BASE64CHAR[(i >> 4) & 0x3f]; + out[2] = (byte) S_BASE64CHAR[(i << 2) & 0x3f]; + out[3] = (byte) S_BASE64PAD; + ostream.write(out, 0, 4); + } + } + + /** + * Outputs base64 representation of the specified byte array to a character stream. + */ + public static void encode(byte[] data, int off, int len, Writer writer) throws IOException { + if (len <= 0) { + return; + } + char[] out = new char[4]; + int rindex = off; + int rest = len - off; + int output = 0; + while (rest >= 3) { + int i = + ((data[rindex] & 0xff) << 16) + ((data[rindex + 1] & 0xff) << 8) + + (data[rindex + 2] & 0xff); + out[0] = S_BASE64CHAR[i >> 18]; + out[1] = S_BASE64CHAR[(i >> 12) & 0x3f]; + out[2] = S_BASE64CHAR[(i >> 6) & 0x3f]; + out[3] = S_BASE64CHAR[i & 0x3f]; + writer.write(out, 0, 4); + rindex += 3; + rest -= 3; + output += 4; + if (output % 76 == 0) { + writer.write("\n"); + } + } + if (rest == 1) { + int i = data[rindex] & 0xff; + out[0] = S_BASE64CHAR[i >> 2]; + out[1] = S_BASE64CHAR[(i << 4) & 0x3f]; + out[2] = S_BASE64PAD; + out[3] = S_BASE64PAD; + writer.write(out, 0, 4); + } else if (rest == 2) { + int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); + out[0] = S_BASE64CHAR[i >> 10]; + out[1] = S_BASE64CHAR[(i >> 4) & 0x3f]; + out[2] = S_BASE64CHAR[(i << 2) & 0x3f]; + out[3] = S_BASE64PAD; + writer.write(out, 0, 4); + } + } + } + + /** + * <p/> + * Utility class for xs:hexbinary. </p> + */ + public static final class HexBinary { + private HexBinary() { + } + + /** + * Converts the string <code>pValue</code> into an array of hex bytes. + */ + public static byte[] decode(String pValue) { + if ((pValue.length() % 2) != 0) { + throw new IllegalArgumentException("A HexBinary string must have even length."); + } + byte[] result = new byte[pValue.length() / 2]; + int j = 0; + int i = 0; + while (i < pValue.length()) { + byte b; + char c = pValue.charAt(i++); + char d = pValue.charAt(i++); + if (c >= '0' && c <= '9') { + b = (byte) ((c - '0') << 4); + } else if (c >= 'A' && c <= 'F') { + b = (byte) ((c - 'A' + 10) << 4); + } else if (c >= 'a' && c <= 'f') { + b = (byte) ((c - 'a' + 10) << 4); + } else { + throw new IllegalArgumentException("Invalid hex digit: " + c); + } + if (d >= '0' && d <= '9') { + b += (byte) (d - '0'); + } else if (d >= 'A' && d <= 'F') { + b += (byte) (d - 'A' + 10); + } else if (d >= 'a' && d <= 'f') { + b += (byte) (d - 'a' + 10); + } else { + throw new IllegalArgumentException("Invalid hex digit: " + d); + } + result[j++] = b; + } + return result; + } + + /** + * Converts the byte array <code>pHexBinary</code> into a string. + */ + public static String encode(byte[] pHexBinary) { + StringBuffer result = new StringBuffer(); + for (int i = 0; i < pHexBinary.length; i++) { + byte b = pHexBinary[i]; + byte c = (byte) ((b & 0xf0) >> 4); + if (c <= 9) { + result.append((char) ('0' + c)); + } else { + result.append((char) ('A' + c - 10)); + } + c = (byte) (b & 0x0f); + if (c <= 9) { + result.append((char) ('0' + c)); + } else { + result.append((char) ('A' + c - 10)); + } + } + return result.toString(); + } + + /** + * Creates a clone of the given byte array. + */ + public static byte[] getClone(byte[] pHexBinary) { + byte[] result = new byte[pHexBinary.length]; + System.arraycopy(pHexBinary, 0, result, 0, pHexBinary.length); + return result; + } + } + + public class XSDDateFormat extends XSDDateTimeFormat { + private static final long serialVersionUID = -1629412916827246627L; + + /** + * Creates a new instance. + */ + public XSDDateFormat() { + super(true, false); + } + } + + /** + * <p/> + * An instance of {@link java.text.Format}, which may be used to parse and format <code>xs:dateTime</code> values. + * </p> + */ + public static class XSDDateTimeFormat extends Format { + private static final long serialVersionUID = -1148332471737068969L; + + final boolean parseDate; + + final boolean parseTime; + + /** + * Creates a new instance. + */ + public XSDDateTimeFormat() { + this(true, true); + } + + XSDDateTimeFormat(boolean pParseDate, boolean pParseTime) { + parseDate = pParseDate; + parseTime = pParseTime; + } + + private void append(StringBuffer pBuffer, int pNum, int pMinLen) { + String s = Integer.toString(pNum); + for (int i = s.length(); i < pMinLen; i++) { + pBuffer.append('0'); + } + pBuffer.append(s); + } + + @Override + public StringBuffer format(Object pCalendar, StringBuffer pBuffer, FieldPosition pPos) { + assert pCalendar != null : "The Calendar argument must not be null."; + assert pBuffer != null : "The StringBuffer argument must not be null."; + assert pPos != null : "The FieldPosition argument must not be null."; + + Calendar cal = (Calendar) pCalendar; + if (parseDate) { + int year = cal.get(Calendar.YEAR); + if (year < 0) { + pBuffer.append('-'); + year = -year; + } + append(pBuffer, year, 4); + pBuffer.append('-'); + append(pBuffer, cal.get(Calendar.MONTH) + 1, 2); + pBuffer.append('-'); + append(pBuffer, cal.get(Calendar.DAY_OF_MONTH), 2); + if (parseTime) { + pBuffer.append('T'); + } + } + if (parseTime) { + append(pBuffer, cal.get(Calendar.HOUR_OF_DAY), 2); + pBuffer.append(':'); + append(pBuffer, cal.get(Calendar.MINUTE), 2); + pBuffer.append(':'); + append(pBuffer, cal.get(Calendar.SECOND), 2); + int millis = cal.get(Calendar.MILLISECOND); + if (millis > 0) { + pBuffer.append('.'); + append(pBuffer, millis, 3); + } + } + TimeZone tz = cal.getTimeZone(); + // JDK 1.4: int offset = tz.getOffset(cal.getTimeInMillis()); + int offset = cal.get(Calendar.ZONE_OFFSET); + if (tz.inDaylightTime(cal.getTime())) { + offset += cal.get(Calendar.DST_OFFSET); + } + if (offset == 0) { + pBuffer.append('Z'); + } else { + if (offset < 0) { + pBuffer.append('-'); + offset = -offset; + } else { + pBuffer.append('+'); + } + int minutes = offset / (60 * 1000); + int hours = minutes / 60; + minutes -= hours * 60; + append(pBuffer, hours, 2); + pBuffer.append(':'); + append(pBuffer, minutes, 2); + } + return pBuffer; + } + + private int parseInt(String pString, int offset, StringBuffer pDigits) { + int length = pString.length(); + int pOffset = offset; + pDigits.setLength(0); + while (pOffset < length) { + char c = pString.charAt(pOffset); + if (Character.isDigit(c)) { + pDigits.append(c); + ++pOffset; + } else { + break; + } + } + return pOffset; + } + + @Override + public Object parseObject(String pString, ParsePosition pParsePosition) { + assert pString != null : "The String argument must not be null."; + assert pParsePosition != null : "The ParsePosition argument must not be null."; + int offset = pParsePosition.getIndex(); + int length = pString.length(); + + boolean isMinus = false; + StringBuffer digits = new StringBuffer(); + int year = 0; + int month = 0; + int mday = 0; + if (parseDate) { + // Sign + if (offset < length) { + char c = pString.charAt(offset); + if (c == '+') { + ++offset; + } else if (c == '-') { + ++offset; + isMinus = true; + } + } + + offset = parseInt(pString, offset, digits); + if (digits.length() < 4) { + pParsePosition.setErrorIndex(offset); + return null; + } + year = Integer.parseInt(digits.toString()); + + if (offset < length && pString.charAt(offset) == '-') { + ++offset; + } else { + pParsePosition.setErrorIndex(offset); + return null; + } + + offset = parseInt(pString, offset, digits); + if (digits.length() != 2) { + pParsePosition.setErrorIndex(offset); + return null; + } + month = Integer.parseInt(digits.toString()); + + if (offset < length && pString.charAt(offset) == '-') { + ++offset; + } else { + pParsePosition.setErrorIndex(offset); + return null; + } + + offset = parseInt(pString, offset, digits); + if (digits.length() != 2) { + pParsePosition.setErrorIndex(offset); + return null; + } + mday = Integer.parseInt(digits.toString()); + + if (parseTime) { + if (offset < length && pString.charAt(offset) == 'T') { + ++offset; + } else { + pParsePosition.setErrorIndex(offset); + return null; + } + } + } else { + year = month = mday = 0; + } + + int hour = 0; + int minute = 0; + int second = 0; + int millis = 0; + if (parseTime) { + offset = parseInt(pString, offset, digits); + if (digits.length() != 2) { + pParsePosition.setErrorIndex(offset); + return null; + } + hour = Integer.parseInt(digits.toString()); + + if (offset < length && pString.charAt(offset) == ':') { + ++offset; + } else { + pParsePosition.setErrorIndex(offset); + return null; + } + + offset = parseInt(pString, offset, digits); + if (digits.length() != 2) { + pParsePosition.setErrorIndex(offset); + return null; + } + minute = Integer.parseInt(digits.toString()); + + if (offset < length && pString.charAt(offset) == ':') { + ++offset; + } else { + pParsePosition.setErrorIndex(offset); + return null; + } + + offset = parseInt(pString, offset, digits); + if (digits.length() != 2) { + pParsePosition.setErrorIndex(offset); + return null; + } + second = Integer.parseInt(digits.toString()); + + if (offset < length && pString.charAt(offset) == '.') { + ++offset; + offset = parseInt(pString, offset, digits); + if (digits.length() > 0) { + millis = Integer.parseInt(digits.toString()); + } else { + millis = 0; + } + } else { + millis = 0; + } + } else { + hour = minute = second = millis = 0; + } + + digits.setLength(0); + digits.append("GMT"); + if (offset < length) { + char c = pString.charAt(offset); + if (c == 'Z') { + // Ignore UTC, it is the default + ++offset; + } else if (c == '+' || c == '-') { + digits.append(c); + ++offset; + for (int i = 0; i < 5; i++) { + if (offset >= length) { + pParsePosition.setErrorIndex(offset); + return null; + } + c = pString.charAt(offset); + if ((i != 2 && Character.isDigit(c)) || (i == 2 && c == ':')) { + digits.append(c); + } else { + pParsePosition.setErrorIndex(offset); + return null; + } + ++offset; + } + } + } + + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(digits.toString())); + cal.set(isMinus ? -year : year, parseDate ? month - 1 : month, mday, hour, minute, second); + cal.set(Calendar.MILLISECOND, millis); + pParsePosition.setIndex(offset); + return cal; + } + } + + public static class XSDTimeFormat extends XSDDateTimeFormat { + private static final long serialVersionUID = 1346506860724640517L; + + /** + * Creates a new instance. + */ + public XSDTimeFormat() { + super(false, true); + } + } + + private static final long MAX_UNSIGNED_INT = (((long) Integer.MAX_VALUE) * 2) + 1; + + private static final int MAX_UNSIGNED_SHORT = Short.MAX_VALUE * 2 + 1; + + public String parseAnySimpleType(String value) { + return value; + } + + public byte[] parseBase64Binary(String value) { + return Base64Binary.decode(value); + } + + public boolean parseBoolean(String value) { + return Boolean.valueOf(value).booleanValue(); + } + + public byte parseByte(String value) { + return Byte.parseByte(value); + } + + public Calendar parseDate(String value) { + XSDDateFormat format = new XSDDateFormat(); + ParsePosition pos = new ParsePosition(0); + Calendar cal = (Calendar) format.parseObject(value, pos); + if (cal == null) { + throw new IllegalArgumentException("Failed to parse date " + value + " at:" + + value.substring(pos.getErrorIndex())); + } + return cal; + } + + public Calendar parseDateTime(String value) { + XSDDateTimeFormat format = new XSDDateTimeFormat(); + ParsePosition pos = new ParsePosition(0); + Calendar cal = (Calendar) format.parseObject(value, pos); + if (cal == null) { + throw new IllegalArgumentException("Failed to parse dateTime " + value + " at:" + + value.substring(pos.getErrorIndex())); + } + return cal; + } + + public BigDecimal parseDecimal(String value) { + return new BigDecimal(value); + } + + public double parseDouble(String value) { + if ("INF".equals(value)) { + return Double.POSITIVE_INFINITY; + } else if ("-INF".equals(value)) { + return Double.NEGATIVE_INFINITY; + } else if ("NaN".equals(value)) { + return Double.NaN; + } else { + return Double.parseDouble(value); + } + } + + public Duration parseDuration(String pDuration) { + try { + return DatatypeFactory.newInstance().newDuration(pDuration); + } catch (DatatypeConfigurationException e) { + throw new IllegalArgumentException(e); + } + } + + public float parseFloat(String value) { + if ("INF".equals(value)) { + return Float.POSITIVE_INFINITY; + } else if ("-INF".equals(value)) { + return Float.NEGATIVE_INFINITY; + } else if ("NaN".equals(value)) { + return Float.NaN; + } else { + return Float.parseFloat(value); + } + } + + public byte[] parseHexBinary(String value) { + return HexBinary.decode(value); + } + + public int parseInt(String value) { + return Integer.parseInt(value); + } + + public BigInteger parseInteger(String value) { + return new BigInteger(value); + } + + public long parseLong(String value) { + return Long.parseLong(value); + } + + public QName parseQName(String value, NamespaceContext context) { + int offset = value.indexOf(':'); + String uri; + String localName; + switch (offset) { + case -1: + localName = value; + uri = context.getNamespaceURI(""); + if (uri == null) { + // Should not happen, indicates an error in the + // NamespaceContext + // implementation + throw new IllegalArgumentException("The default prefix is not bound."); + } + break; + case 0: + throw new IllegalArgumentException("Default prefix must be indicated by not using a colon: " + + value); + default: + String prefix = value.substring(0, offset); + localName = value.substring(offset + 1); + uri = context.getNamespaceURI(prefix); + if (uri == null) { + throw new IllegalArgumentException("The prefix " + prefix + " is not bound."); + } + } + return new QName(uri, localName); + } + + public short parseShort(String value) { + return Short.parseShort(value); + } + + public String parseString(String value) { + return value; + } + + public Calendar parseTime(String value) { + XSDTimeFormat format = new XSDTimeFormat(); + ParsePosition pos = new ParsePosition(0); + Calendar cal = (Calendar) format.parseObject(value, pos); + if (cal == null) { + throw new IllegalArgumentException("Failed to parse time " + value + " at:" + + value.substring(pos.getErrorIndex())); + } + return cal; + } + + public long parseUnsignedInt(String value) { + long l = Long.parseLong(value); + if (l < 0) { + throw new IllegalArgumentException("Failed to parse UnsignedInt " + value + + ": result is negative"); + } + if (l > MAX_UNSIGNED_INT) { + throw new IllegalArgumentException("Failed to parse UnsignedInt " + value + + ": result exceeds maximum value " + MAX_UNSIGNED_INT); + } + return l; + } + + public int parseUnsignedShort(String value) { + int i = Integer.parseInt(value); + if (i < 0) { + throw new IllegalArgumentException("Failed to parse UnsignedShort " + value + + ": result is negative"); + } + if (i > MAX_UNSIGNED_SHORT) { + throw new IllegalArgumentException("Failed to parse UnsignedShort " + value + + ": result exceeds maximum value " + MAX_UNSIGNED_SHORT); + } + return i; + } + + public String printAnySimpleType(String value) { + return value; + } + + public String printBase64Binary(byte[] value) { + return Base64Binary.encode(value); + } + + public String printBoolean(boolean value) { + return (value ? Boolean.TRUE : Boolean.FALSE).toString(); + } + + public String printByte(byte value) { + return Byte.toString(value); + } + + public String printDate(Calendar value) { + return new XSDDateFormat().format(value); + } + + public String printDateTime(Calendar value) { + return new XSDDateTimeFormat().format(value); + } + + public String printDecimal(BigDecimal value) { + return value.toString(); + } + + public String printDouble(double value) { + return Double.toString(value); + } + + public String printDuration(Duration pDuration) { + return pDuration.toString(); + } + + public String printFloat(float value) { + return Float.toString(value); + } + + public String printHexBinary(byte[] value) { + return HexBinary.encode(value); + } + + public String printInt(int value) { + return Integer.toString(value); + } + + public String printInteger(BigInteger value) { + return value.toString(); + } + + public String printLong(long value) { + return Long.toString(value); + } + + public String printQName(QName value, NamespaceContext context) { + String prefix = context.getPrefix(value.getNamespaceURI()); + if (prefix == null) { + throw new IllegalArgumentException("The namespace URI " + value.getNamespaceURI() + + " is not bound."); + } else if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) { + return value.getLocalPart(); + } else { + return prefix + ":" + value.getLocalPart(); + } + } + + public String printShort(short value) { + return Short.toString(value); + } + + public String printString(String value) { + return value; + } + + public String printTime(Calendar value) { + return new XSDTimeFormat().format(value); + } + + public String printUnsignedInt(long value) { + return Long.toString(value); + } + + public String printUnsignedShort(int value) { + return Integer.toString(value); + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/DOMNode2JavaBeanTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/DOMNode2JavaBeanTransformer.java new file mode 100644 index 0000000000..2f95c2a9c6 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/DOMNode2JavaBeanTransformer.java @@ -0,0 +1,97 @@ +/*
+ * 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.databinding.javabeans;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Transformer to convert data from DOM Node to JavaBean
+ *
+ * @version $Rev$ $Date$
+ */
+public class DOMNode2JavaBeanTransformer extends XML2JavaBeanTransformer<Node> {
+
+ @Override
+ public Node getRootElement(Node element) throws XML2JavaMapperException {
+ if (element instanceof Document) {
+ return ((Document)element).getDocumentElement();
+ } else {
+ return element;
+ }
+
+ }
+
+ @Override
+ public Iterator<Node> getChildElements(Node parent) throws XML2JavaMapperException {
+ NodeList nodeList = parent.getChildNodes();
+ List<Node> nodeArrayList = new ArrayList<Node>(nodeList.getLength());
+ for (int count = 0; count < nodeList.getLength(); ++count) {
+ nodeArrayList.add(nodeList.item(count));
+ }
+
+ return nodeArrayList.iterator();
+ }
+
+ @Override
+ public String getElementName(Node element) throws XML2JavaMapperException {
+ return element.getLocalName();
+ }
+
+ @Override
+ public String getText(Node element) throws XML2JavaMapperException {
+ if (element instanceof Document) {
+ element = ((Document)element).getDocumentElement();
+ }
+ return element.getTextContent();
+ }
+
+ @Override
+ public boolean isTextElement(Node element) throws XML2JavaMapperException {
+ return element.getNodeType() == Node.TEXT_NODE;
+ }
+
+ @Override
+ public boolean isTextOnly(Node element) throws XML2JavaMapperException {
+ NodeList childNodes = element.getChildNodes();
+ return childNodes.getLength() == 1 && isTextElement(childNodes.item(0));
+ }
+
+ @Override
+ public Node getFirstChildWithName(Node element, QName name) throws XML2JavaMapperException {
+ Node child;
+ for (child = element.getFirstChild();
+ child != null && !(child.getNodeName() == name.getLocalPart()
+ && child.getNamespaceURI() == name.getNamespaceURI()) ;
+ child = child.getNextSibling()) {
+ }
+ return child;
+ }
+
+ @Override
+ public Class getSourceType() {
+ return Node.class;
+ }
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/Java2XMLMapperException.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/Java2XMLMapperException.java new file mode 100644 index 0000000000..9615f43572 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/Java2XMLMapperException.java @@ -0,0 +1,69 @@ +/*
+ * 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.databinding.javabeans;
+
+import javax.xml.namespace.QName;
+
+/**
+ * This exception is used to encapsulate and rethrow exceptions that arise out
+ * of converting JavaBean objects to XML
+ *
+ * @version $Rev$ $Date$
+ */
+public class Java2XMLMapperException extends RuntimeException {
+ private static final long serialVersionUID = 6811924384399578686L;
+
+ private QName xmlElementName;
+ private String javaFieldName;
+ private Class javaType;
+
+ public Java2XMLMapperException(String message) {
+ super(message);
+ }
+
+ public Java2XMLMapperException(Throwable cause) {
+ super(cause);
+ }
+
+ public String getJavaFieldName() {
+ return javaFieldName;
+ }
+
+ public void setJavaFieldName(String javaFieldName) {
+ this.javaFieldName = javaFieldName;
+ }
+
+ public Class getJavaType() {
+ return javaType;
+ }
+
+ public void setJavaType(Class javaType) {
+ this.javaType = javaType;
+ }
+
+ public QName getXmlElementName() {
+ return xmlElementName;
+ }
+
+ public void setXmlElementName(QName xmlElementName) {
+ this.xmlElementName = xmlElementName;
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2DOMNodeTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2DOMNodeTransformer.java new file mode 100644 index 0000000000..58f594751a --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2DOMNodeTransformer.java @@ -0,0 +1,79 @@ +/*
+ * 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.databinding.javabeans;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tuscany.sca.databinding.impl.DOMHelper;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Transformer to convert data from a JavaBean object to DOM Node
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaBean2DOMNodeTransformer extends JavaBean2XMLTransformer<Node> {
+
+ public static final String COLON = ":";
+ private Document factory;
+
+ public JavaBean2DOMNodeTransformer() {
+ super();
+ try {
+ factory = DOMHelper.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new Java2XMLMapperException(e);
+ }
+ }
+
+ @Override
+ public void appendChild(Node parentElement, Node childElement) throws Java2XMLMapperException {
+ parentElement.appendChild(childElement);
+ }
+
+ @Override
+ public Node createElement(QName qName) throws Java2XMLMapperException {
+ String qualifedName =
+ (qName.getPrefix() == null || qName.getPrefix().length() <= 0) ? qName.getLocalPart()
+ : qName.getPrefix() + COLON + qName.getLocalPart();
+ return factory.createElementNS(qName.getNamespaceURI(), qualifedName);
+ }
+
+ @Override
+ public void appendText(Node parentElement, String textData) throws Java2XMLMapperException {
+ Node textNode;
+ if (textData != null) {
+ textNode = factory.createTextNode(textData);
+ } else {
+ Attr nil = factory.createAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:nil");
+ nil.setValue("true");
+ textNode = nil;
+ }
+ appendChild(parentElement, textNode);
+ }
+
+ @Override
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLStreamReaderTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLStreamReaderTransformer.java new file mode 100644 index 0000000000..4942fef0da --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLStreamReaderTransformer.java @@ -0,0 +1,68 @@ +/* + * 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.databinding.javabeans; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.xml.BeanXMLStreamReaderImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Transformer to convert data from a JavaBean object to XMLStreamReader. + * + * @version $Rev$ $Date$ + */ +public class JavaBean2XMLStreamReaderTransformer extends BaseTransformer<Object, XMLStreamReader> implements + PullTransformer<Object, XMLStreamReader> { + + public XMLStreamReader transform(Object source, TransformationContext context) { + try { + javax.xml.namespace.QName name = null; + if (context != null) { + Object logical = context.getSourceDataType().getLogical(); + if (logical instanceof XMLType) { + name = ((XMLType)logical).getElementName(); + } + } + return new BeanXMLStreamReaderImpl(name, source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 50; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java new file mode 100644 index 0000000000..b96b394bb8 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java @@ -0,0 +1,262 @@ +/*
+ * 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.databinding.javabeans;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+
+/**
+ * Transformer to convert data from a JavaBean object to xml
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class JavaBean2XMLTransformer<T> extends BaseTransformer<Object, T> implements
+ PullTransformer<Object, T> {
+
+ public static final String GET = "get";
+ public static final String PREFIX = "n";
+ public static final String PERIOD = ".";
+ public static final String FWD_SLASH = "/";
+ public static final String HTTP = "http://";
+ private static int prefixCount = 1;
+
+ protected SimpleTypeMapperImpl mapper;
+
+ public JavaBean2XMLTransformer() {
+ this.mapper = new SimpleTypeMapperImpl();
+ }
+
+ public T transform(Object source, TransformationContext context) {
+ QName rootElement = null;
+ if (context != null) {
+ DataType<?> type = context.getTargetDataType();
+ if (type != null) {
+ Object logical = type.getLogical();
+ if (logical instanceof XMLType) {
+ rootElement = ((XMLType)logical).getElementName();
+ }
+ }
+ }
+ //FIXME See how/if we still need to get the metadata here
+ //QName rootElementName = (QName)context.getTargetDataType().getMetadata("RootElementName");
+ //if (rootElementName == null) {
+ QName rootElementName = new QName(resolveRootElementName(source.getClass()));
+ //}
+
+ T root = createElement(rootElementName);
+ appendChildElements(root, resolveElementName(source.getClass()), source.getClass(), source, context);
+ return root;
+ }
+
+ private void appendChildElements(T parent,
+ QName elementName,
+ Class javaType,
+ Object javaObject,
+ TransformationContext context) {
+ T element = null;
+ if (javaObject != null) {
+ if (javaType.isPrimitive() || isSimpleJavaType(javaObject)) {
+ appendText(parent, mapper.toXMLLiteral(null, javaObject, context));
+ } else if (javaType.isArray()) {
+ int size = Array.getLength(javaObject);
+ for (int count = 0; count < size; ++count) {
+ Object item = Array.get(javaObject, count);
+ element = createElement(elementName);
+ appendChild(parent, element);
+ appendChildElements(element, elementName, javaType.getComponentType(), item, context);
+ }
+ } else {
+ Field[] javaFields = javaType.getFields();
+ for (Field aField : javaFields) {
+ try {
+ QName fieldElementName = new QName(aField.getName());
+ if (!aField.getType().isArray()) {
+ element = createElement(fieldElementName);
+ appendChild(parent, element);
+ appendChildElements(element,
+ fieldElementName,
+ aField.getType(),
+ aField.get(javaObject),
+ context);
+ } else {
+ appendChildElements(parent,
+ fieldElementName,
+ aField.getType(),
+ aField.get(javaObject),
+ context);
+ }
+ } catch (IllegalAccessException e) {
+ Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e);
+ java2xmlEx.setJavaFieldName(aField.getName());
+ java2xmlEx.setJavaType(javaType);
+ throw java2xmlEx;
+ }
+ }
+
+ Method[] methods = javaType.getMethods();
+ String fieldName = null;
+ for (Method aMethod : methods) {
+ try {
+ if (Modifier.isPublic(aMethod.getModifiers()) && aMethod.getName().startsWith(GET)
+ && aMethod.getParameterTypes().length == 0
+ && isMappedGetter(aMethod.getName())) {
+ fieldName = resolveFieldFromMethod(aMethod.getName());
+ try {
+ javaType.getField(fieldName);
+ } catch (NoSuchFieldException e) {
+ QName fieldElementName = new QName(fieldName);
+ if (aMethod.getReturnType().isArray()) {
+ appendChildElements(parent, fieldElementName, aMethod.getReturnType(), aMethod
+ .invoke(javaObject, new Object[0]), context);
+ } else {
+ element = createElement(fieldElementName);
+ appendChild(parent, element);
+ appendChildElements(element, fieldElementName, aMethod.getReturnType(), aMethod
+ .invoke(javaObject, new Object[0]), context);
+ }
+ }
+ }
+ } catch (IllegalAccessException e) {
+ Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e);
+ java2xmlEx.setJavaFieldName(fieldName);
+ java2xmlEx.setJavaType(javaType);
+ throw java2xmlEx;
+ } catch (InvocationTargetException e) {
+ Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e);
+ java2xmlEx.setJavaFieldName(fieldName);
+ java2xmlEx.setJavaType(javaType);
+ throw java2xmlEx;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Subclasses can override this method to prevent some getter methods
+ * from being mapped. The default implementation provided by this class
+ * maps all getter methods.
+ */
+ protected boolean isMappedGetter(String methodName) {
+ return true;
+ }
+
+ @Override
+ public String getSourceDataBinding() {
+ return JavaBeansDataBinding.NAME;
+ }
+
+ @Override
+ public Class<Object> getSourceType() {
+ return Object.class;
+ }
+
+ private boolean isSimpleJavaType(Object javaObject) {
+ if (javaObject instanceof String) {
+ return true;
+ }
+ if (javaObject instanceof Byte || javaObject instanceof Character
+ || javaObject instanceof Short
+ || javaObject instanceof Integer
+ || javaObject instanceof Long
+ || javaObject instanceof Float
+ || javaObject instanceof Double
+ || javaObject instanceof Boolean) {
+ return true;
+ }
+ if (javaObject instanceof GregorianCalendar || javaObject instanceof Date
+ || javaObject instanceof XMLGregorianCalendar
+ || javaObject instanceof byte[]
+ || javaObject instanceof QName) {
+ return true;
+ }
+ return false;
+ }
+
+ private String resolveRootElementName(Class javaType) {
+ if (javaType.isArray()) {
+ return javaType.getComponentType().getSimpleName() + "_collection";
+ } else {
+ return javaType.getSimpleName() + "_instance";
+ }
+ }
+
+ private QName resolveElementName(Class javaType) {
+ if (javaType.isArray()) {
+ return new QName(javaType.getComponentType().getSimpleName());
+ } else {
+ return new QName(javaType.getSimpleName());
+ }
+ }
+
+ private String resolveFieldFromMethod(String methodName) {
+ StringBuffer fieldName = new StringBuffer();
+ fieldName.append(Character.toLowerCase(methodName.charAt(GET.length())));
+ fieldName.append(methodName.substring(GET.length() + 1));
+ return fieldName.toString();
+ }
+
+ public String getNexPrefix() {
+ return PREFIX + prefixCount++;
+ }
+
+ @Override
+ public int getWeight() {
+ return JavaBeansDataBinding.HEAVY_WEIGHT;
+ }
+
+ /**
+ * Create an element with the given name
+ * @param qName
+ * @return
+ * @throws Java2XMLMapperException
+ */
+ public abstract T createElement(QName qName) throws Java2XMLMapperException;
+
+ /**
+ * Create a text node and add it to the parent
+ * @param parentElement
+ * @param textData
+ * @throws Java2XMLMapperException
+ */
+ public abstract void appendText(T parentElement, String textData) throws Java2XMLMapperException;
+
+ /**
+ * Add the child element to the parent
+ * @param parentElement
+ * @param childElement
+ * @throws Java2XMLMapperException
+ */
+ public abstract void appendChild(T parentElement, T childElement) throws Java2XMLMapperException;
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java new file mode 100644 index 0000000000..fb04014051 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java @@ -0,0 +1,139 @@ +/*
+ * 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.databinding.javabeans;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import org.apache.tuscany.sca.databinding.impl.BaseDataBinding;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+
+/**
+ * DataBinding for JavaBeans
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaBeansDataBinding extends BaseDataBinding {
+ /**
+ * Defining a weight to a very high number so that the transformer won't be picked
+ * up by other paths unless it's the only available path
+ */
+ public static final int HEAVY_WEIGHT = 10000;
+ public static final String NAME = "java:complexType";
+
+ public JavaBeansDataBinding() {
+ super(NAME, Object.class);
+ }
+
+ protected JavaBeansDataBinding(String name, Class<?> baseType) {
+ super(name, baseType);
+ }
+
+ @Override
+ public Object copy(Object arg, DataType dataType, Operation operation) {
+ if (arg == null) {
+ return null;
+ }
+ final Class clazz = arg.getClass();
+ if (String.class == clazz || clazz.isPrimitive()
+ || Number.class.isAssignableFrom(clazz)
+ || Boolean.class.isAssignableFrom(clazz)
+ || Character.class.isAssignableFrom(clazz)
+ || Byte.class.isAssignableFrom(clazz)) {
+ // Immutable classes
+ return arg;
+ }
+ try {
+ if (arg instanceof Serializable) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = getObjectOutputStream(bos);
+ oos.writeObject(arg);
+ oos.close();
+ bos.close();
+
+ // Work out which ClassLoader to use for deserializing arg
+ // We want to use:
+ // * The ClassLoader of arg if it is not the System ClassLoader
+ // * The ThreadContext ClassLoader if the ClassLoader of arg is the System ClassLoader
+ // because Collection classes are loaded by the System ClassLoader but their contents
+ // may be loaded from another ClassLoader
+ //
+ ClassLoader classLoaderToUse = clazz.getClassLoader();
+ if (classLoaderToUse == null)
+ {
+ // ClassLoader of arg is the System ClassLoader so we will use the ThreadContext ClassLoader
+ // instead
+ classLoaderToUse = Thread.currentThread().getContextClassLoader();
+ }
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ ObjectInputStream ois = getObjectInputStream(bis, classLoaderToUse);
+ Object objectCopy = ois.readObject();
+ ois.close();
+ bis.close();
+ return objectCopy;
+ } else {
+ // return arg;
+ throw new IllegalArgumentException("Argument type '" + arg.getClass().getCanonicalName() + "' is not Serializable. " +
+ " Pass-by-value cannot be performed on this argument");
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Pass-by-value is not supported for the given object", e);
+ }
+ }
+
+ protected ObjectOutputStream getObjectOutputStream(OutputStream os) throws IOException {
+ return new ObjectOutputStream(os);
+ }
+
+ protected ObjectInputStream getObjectInputStream(InputStream is, final ClassLoader cl) throws IOException {
+ ObjectInputStream ois = new ObjectInputStream(is) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ try {
+ return Class.forName(desc.getName(), false, cl);
+ } catch (ClassNotFoundException e) {
+ try {
+ // For OSGi, use context ClassLoader if the bundle ClassLoader cannot load the class
+ if (cl != Thread.currentThread().getContextClassLoader()) {
+ return Class.forName(desc.getName(), false, Thread.currentThread().getContextClassLoader());
+ }
+ } catch (ClassNotFoundException e1) {
+ // ignore
+ } catch (NoClassDefFoundError e1) {
+ // ignore
+ }
+ return super.resolveClass(desc);
+ }
+ }
+
+ };
+ return ois;
+ }
+
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaExceptionDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaExceptionDataBinding.java new file mode 100644 index 0000000000..7ae64c6a27 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaExceptionDataBinding.java @@ -0,0 +1,35 @@ +/*
+ * 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.databinding.javabeans;
+
+
+/**
+ * DataBinding for Java Exceptions
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaExceptionDataBinding extends JavaBeansDataBinding {
+
+ public static final String NAME = "java:exception";
+
+ public JavaExceptionDataBinding() {
+ super(NAME, null);
+ }
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/SimpleJavaDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/SimpleJavaDataBinding.java new file mode 100644 index 0000000000..11c82e062c --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/SimpleJavaDataBinding.java @@ -0,0 +1,79 @@ +/* + * 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.databinding.javabeans; + + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.xml.XMLStringDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * DataBinding for Java simple types + * + * @version $Rev$ $Date$ + */ +public class SimpleJavaDataBinding extends BaseDataBinding { + public static final String NAME = "java:simpleType"; + + public SimpleJavaDataBinding() { + super(NAME, Object.class); + } + + @Override + public Object copy(Object arg, DataType dataType, Operation operation) { + if (arg instanceof byte[]) { + return ((byte[])arg).clone(); + } + return arg; + } + + @Override + public boolean introspect(DataType type, Operation operation) { + Class<?> cls = type.getPhysical(); + if (cls == Object.class) { + return false; + } + // HACK: [rfeng] By pass the one know to XMLString + String db = type.getDataBinding(); + if (db != null && (XMLStringDataBinding.NAME.equals(db) || XMLStringDataBinding.ALIASES[0].equals(db))) { + return false; + } + if (SimpleTypeMapperImpl.JAVA2XML.keySet().contains(cls)) { + type.setDataBinding(NAME); + QName elementName = null; + Object logical = type.getLogical(); + if (logical instanceof XMLType) { + elementName = ((XMLType)logical).getElementName(); + } + TypeInfo typeInfo = SimpleTypeMapperImpl.getXMLType(cls); + type.setLogical(new XMLType(elementName, typeInfo == null ? null : typeInfo.getQName())); + return true; + } else { + return false; + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaBeanTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaBeanTransformer.java new file mode 100644 index 0000000000..06feeffabd --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaBeanTransformer.java @@ -0,0 +1,329 @@ +/*
+ * 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.databinding.javabeans;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+
+/**
+ * Transformer to convert data from XML to JavaBean
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class XML2JavaBeanTransformer<T> extends BaseTransformer<T, Object> implements
+ PullTransformer<T, Object> {
+
+ public static final String SET = "set";
+ public static final QName QNAME_MESSAGE = new QName("message");
+
+ protected SimpleTypeMapperImpl mapper;
+
+ public XML2JavaBeanTransformer() {
+ this.mapper = new SimpleTypeMapperImpl();
+ }
+
+ @Override
+ public int getWeight() {
+ return JavaBeansDataBinding.HEAVY_WEIGHT;
+ }
+
+ public Object transform(T source, TransformationContext context) {
+ //FIXME why is the logical type sometimes a Class instead of an XMLType?
+ if (context.getSourceDataType().getLogical() instanceof XMLType) {
+ XMLType xmlType = (XMLType) context.getSourceDataType().getLogical();
+ return toJavaObject(xmlType.getTypeName(), getRootElement(source), context);
+ } else {
+ return toJavaObject(null, getRootElement(source), context);
+ }
+ }
+
+ public Object toJavaObject(QName xmlType, T xmlElement, TransformationContext context) {
+ if (xmlType != null && SimpleTypeMapperImpl.isSimpleXSDType(xmlType)) {
+ return mapper.toJavaObject(xmlType, getText(xmlElement), context);
+ } else {
+ Class<?> javaType = (Class<?>)context.getTargetDataType().getPhysical();
+ return createJavaObject(xmlElement, javaType, context);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <L> L createJavaObject(T element, Class<L> javaType, TransformationContext context)
+ throws XML2JavaMapperException {
+ if (isTextOnly(element)) {
+ return (L) mapper.toJavaObject(SimpleTypeMapperImpl.getXMLType(javaType).getQName(),
+ getText(element),
+ context);
+ } else {
+ String fieldName = null;
+ try {
+ L javaInstance;
+ T detailMsg = null;
+ if (Throwable.class.isAssignableFrom(javaType)) {
+ T msgElement = getFirstChildWithName(element, QNAME_MESSAGE);
+ if (msgElement != null && isTextOnly(msgElement)) {
+ detailMsg = msgElement; // skip this when handling child elements
+ Constructor constructor = javaType.getConstructor(new Class[] {String.class});
+ javaInstance = (L)constructor.newInstance(new Object[] {getText(detailMsg)});
+ } else {
+ javaInstance = javaType.newInstance();
+ }
+ } else {
+ javaInstance = javaType.newInstance();
+ }
+ Map<Field, List<Object>> arrayFields = new Hashtable<Field, List<Object>>();
+ Map<Method, List<Object>> arraySetters = new Hashtable<Method, List<Object>>();
+
+ for (Iterator<T> childElements = getChildElements(element); childElements.hasNext(); ) {
+ T childElement = childElements.next();
+ if (!isTextElement(childElement) && childElement != detailMsg) {
+ fieldName = getElementName(childElement);
+ try {
+ Field javaField = javaType.getField(fieldName);
+ setFieldValue(javaInstance,
+ javaField,
+ childElement,
+ arrayFields,
+ context);
+
+ } catch (NoSuchFieldException e1) {
+ setFieldValueUsingSetter(javaType,
+ javaInstance,
+ fieldName,
+ childElement,
+ arraySetters,
+ context);
+ }
+ }
+ }
+
+ setArrayValues(javaInstance, arrayFields, arraySetters);
+ return javaInstance;
+ } catch (Exception e2) {
+ XML2JavaMapperException xml2JavaEx = new XML2JavaMapperException(e2);
+ xml2JavaEx.setJavaType(javaType);
+ xml2JavaEx.setJavaFieldName(fieldName);
+ throw xml2JavaEx;
+ }
+ }
+ }
+
+ private void setFieldValue(Object javaInstance,
+ Field javaField,
+ T fieldValue,
+ Map<Field, List<Object>> arrayFields,
+ TransformationContext context) throws IllegalAccessException {
+ Class<?> javaFieldType = (Class<?>) javaField.getType();
+
+ if (javaFieldType.isArray()) {
+ Class<?> componentType = javaFieldType.getComponentType();
+ List<Object> fldValueArray = arrayFields.get(javaField);
+ if (fldValueArray == null) {
+ fldValueArray = new ArrayList<Object>();
+ arrayFields.put(javaField, fldValueArray);
+ }
+ fldValueArray.add(createJavaObject(fieldValue, componentType, context));
+ } else {
+ javaField.setAccessible(true);
+ javaField.set(javaInstance, createJavaObject(fieldValue, javaFieldType, context));
+ }
+ }
+
+ private void setFieldValueUsingSetter(Class javaType,
+ Object javaInstance,
+ String fieldName,
+ T fieldValue,
+ Map<Method, List<Object>> arraySetters,
+ TransformationContext context) throws IllegalAccessException,
+ InvocationTargetException {
+ char firstChar = Character.toUpperCase(fieldName.charAt(0));
+ StringBuilder methodName = new StringBuilder(SET + fieldName);
+ methodName.setCharAt(SET.length(), firstChar);
+ boolean methodNotFound = true;
+
+ for (int methodCount = 0; methodNotFound && methodCount < javaType.getMethods().length; ++methodCount) {
+ Method aMethod = javaType.getMethods()[methodCount];
+ if (aMethod.getName().equals(methodName.toString())
+ && aMethod.getParameterTypes().length == 1) {
+ Class<?> paramType = aMethod.getParameterTypes()[0];
+
+ if (paramType.isArray()) {
+ Class<?> componentType = paramType.getComponentType();
+ List<Object> setterValueArray = arraySetters.get(aMethod);
+ if (setterValueArray == null) {
+ setterValueArray = new ArrayList<Object>();
+ arraySetters.put(aMethod, setterValueArray);
+ }
+ setterValueArray.add(createJavaObject(fieldValue, componentType, context));
+ } else {
+ aMethod.invoke(javaInstance, new Object[] {createJavaObject(fieldValue,
+ paramType,
+ context)});
+ }
+ methodNotFound = false;
+ }
+ }
+
+ if (methodNotFound) {
+ XML2JavaMapperException xml2JavaEx =
+ new XML2JavaMapperException("No field or setter method to configure xml data");
+ xml2JavaEx.setJavaFieldName(fieldName);
+ xml2JavaEx.setJavaType(javaType);
+ throw xml2JavaEx;
+ }
+ }
+
+ private void setArrayValues(Object javaInstance,
+ Map<Field, List<Object>> arrayFields,
+ Map<Method, List<Object>> arraySetters) throws IllegalAccessException,
+ InvocationTargetException {
+ if (arrayFields.size() > 0) {
+ for (Field javaField : arrayFields.keySet()) {
+ javaField.setAccessible(true);
+
+ if (javaField.getType().getComponentType().isPrimitive()) {
+ javaField.set(javaInstance, createPrimitiveArray(javaField.getType()
+ .getComponentType(),
+ arrayFields.get(javaField)));
+ } else {
+ javaField.set(javaInstance,
+ createNonPrimitiveArray(javaField.getType().getComponentType(),
+ arrayFields.get(javaField)));
+ }
+ }
+ }
+
+ if (arraySetters.size() > 0) {
+ for (Method aMethod : arraySetters.keySet()) {
+ Class paramType = aMethod.getParameterTypes()[0];
+ if (paramType.getComponentType().isPrimitive()) {
+ aMethod.invoke(javaInstance,
+ new Object[] {createPrimitiveArray(paramType.getComponentType(),
+ arraySetters.get(aMethod))});
+ } else {
+ aMethod.invoke(javaInstance,
+ new Object[] {createNonPrimitiveArray(paramType.getComponentType(),
+ arraySetters.get(aMethod))});
+ }
+ }
+ }
+ }
+
+ private Object createNonPrimitiveArray(Class fieldType, List values) {
+ Object objectArray = Array.newInstance(fieldType, values.size());
+ for (int count = 0; count < values.size(); ++count) {
+ Array.set(objectArray, count, values.get(count));
+ }
+ return objectArray;
+ }
+
+ private Object createPrimitiveArray(Class fieldType, List values) {
+ if (fieldType.isPrimitive()) {
+ if (fieldType.getName().equals("int")) {
+ int[] primitiveValues = new int[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Integer) values.get(count)).intValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("float")) {
+ float[] primitiveValues = new float[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Float) values.get(count)).floatValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("boolean")) {
+ boolean[] primitiveValues = new boolean[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Boolean) values.get(count)).booleanValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("char")) {
+ char[] primitiveValues = new char[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Character) values.get(count)).charValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("byte")) {
+ byte[] primitiveValues = new byte[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Byte) values.get(count)).byteValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("short")) {
+ short[] primitiveValues = new short[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Short) values.get(count)).shortValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("long")) {
+ long[] primitiveValues = new long[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Long) values.get(count)).longValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("double")) {
+ double[] primitiveValues = new double[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Double) values.get(count)).doubleValue();
+ }
+ return primitiveValues;
+ }
+ }
+ return values;
+ }
+
+ public abstract String getText(T source) throws XML2JavaMapperException;
+
+ public abstract Iterator<T> getChildElements(T parent) throws XML2JavaMapperException;
+
+ public abstract String getElementName(T element) throws XML2JavaMapperException;
+
+ public abstract boolean isTextElement(T element) throws XML2JavaMapperException;
+
+ public abstract boolean isTextOnly(T element) throws XML2JavaMapperException;
+
+ public abstract T getFirstChildWithName(T element, QName name) throws XML2JavaMapperException;
+
+ public abstract T getRootElement(T element) throws XML2JavaMapperException;
+
+ @Override
+ public Class<Object> getTargetType() {
+ return Object.class;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return JavaBeansDataBinding.NAME;
+ }
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaMapperException.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaMapperException.java new file mode 100644 index 0000000000..a723fd445c --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaMapperException.java @@ -0,0 +1,76 @@ +/*
+ * 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.databinding.javabeans;
+
+import javax.xml.namespace.QName;
+
+/**
+ * This exception is used to encapsulate and rethrow exceptions that arise out
+ * of converting XML Data to Java Objects.
+ *
+ * @version $Rev$ $Date$
+ */
+public class XML2JavaMapperException extends RuntimeException {
+ private static final long serialVersionUID = 6596530102591630642L;
+
+ private QName xmlElementName;
+ private String javaFieldName;
+ private Class javaType;
+
+ public XML2JavaMapperException(String message) {
+ super(message);
+ }
+
+ public XML2JavaMapperException(Throwable cause) {
+ super(cause);
+ }
+
+ public QName getXmlElementName() {
+ return xmlElementName;
+ }
+
+ public void setXmlElementName(QName xmlElementName) {
+ this.xmlElementName = xmlElementName;
+ }
+
+ public String getJavaFieldName() {
+ return javaFieldName;
+ }
+
+ public void setJavaFieldName(String javaFieldName) {
+ this.javaFieldName = javaFieldName;
+ }
+
+ public Class getJavaType() {
+ return javaType;
+ }
+
+ public void setJavaType(Class javaType) {
+ this.javaType = javaType;
+ }
+
+ @Override
+ public String getMessage() {
+ return super.getMessage() + " <" + getJavaFieldName() + "> " + " in <" + getJavaType() + ">";
+ }
+
+
+
+}
diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/DataTypeHelper.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/DataTypeHelper.java new file mode 100644 index 0000000000..1e39150f4a --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/DataTypeHelper.java @@ -0,0 +1,165 @@ +/* + * 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.databinding.util; + +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataTypeHelper { + private DataTypeHelper() { + } + + /** + * Find all classes referenced by this data type though java generics + * @param d + * @return + */ + public static Set<Class<?>> findClasses(DataType d) { + Set<Class<?>> classes = new HashSet<Class<?>>(); + Set<Type> visited = new HashSet<Type>(); + findClasses(d, classes, visited); + return classes; + } + + private static void findClasses(DataType d, Set<Class<?>> classes, Set<Type> visited) { + if (d == null) { + return; + } + classes.add(d.getPhysical()); + if (d.getPhysical() != d.getGenericType()) { + findClasses(d.getGenericType(), classes, visited); + } + } + + /** + * Find referenced classes in the generic type + * @param type + * @param classSet + * @param visited + */ + private static void findClasses(Type type, Set<Class<?>> classSet, Set<Type> visited) { + if (visited.contains(type) || type == null) { + return; + } + visited.add(type); + if (type instanceof Class) { + Class<?> cls = (Class<?>)type; + if (!cls.isInterface()) { + classSet.add(cls); + } + return; + } else if (type instanceof ParameterizedType) { + ParameterizedType pType = (ParameterizedType)type; + findClasses(pType.getRawType(), classSet, visited); + for (Type t : pType.getActualTypeArguments()) { + findClasses(t, classSet, visited); + } + } else if (type instanceof TypeVariable) { + TypeVariable<?> tv = (TypeVariable<?>)type; + for (Type t : tv.getBounds()) { + findClasses(t, classSet, visited); + } + } else if (type instanceof GenericArrayType) { + GenericArrayType gType = (GenericArrayType)type; + findClasses(gType, classSet, visited); + } else if (type instanceof WildcardType) { + WildcardType wType = (WildcardType)type; + for (Type t : wType.getLowerBounds()) { + findClasses(t, classSet, visited); + } + for (Type t : wType.getUpperBounds()) { + findClasses(t, classSet, visited); + } + } + } + + /** + * Get all the data types in the interface + * @param intf The interface + * @param useWrapper Use wrapper classes? + * @return A list of DataTypes + */ + public static List<DataType> getDataTypes(Interface intf, boolean useWrapper) { + List<DataType> dataTypes = new ArrayList<DataType>(); + for (Operation op : intf.getOperations()) { + getDataTypes(dataTypes, op, useWrapper); + } + return dataTypes; + } + + /** + * Get all the data types in the operation + * @param op The operaiton + * @param useWrapper Use wrapper classes? + * @return A list of DataTypes + */ + public static List<DataType> getDataTypes(Operation op, boolean useWrapper) { + List<DataType> dataTypes = new ArrayList<DataType>(); + getDataTypes(dataTypes, op, useWrapper); + return dataTypes; + } + + private static void getDataTypes(List<DataType> dataTypes, Operation op, boolean useWrapper) { + WrapperInfo wrapper = op.getWrapper(); + if (useWrapper && wrapper != null) { + DataType dt1 = wrapper.getInputWrapperType(); + if (dt1 != null) { + dataTypes.add(dt1); + } + DataType dt2 = wrapper.getOutputWrapperType(); + if (dt2 != null) { + dataTypes.add(dt2); + } + } + // FIXME: [rfeng] We may need to find the referenced classes in the child types + // else + { + for (DataType dt1 : op.getInputType().getLogical()) { + dataTypes.add(dt1); + } + DataType dt2 = op.getOutputType(); + if (dt2 != null) { + dataTypes.add(dt2); + } + } + for (DataType<DataType> dt3 : op.getFaultTypes()) { + DataType dt4 = dt3.getLogical(); + if (dt4 != null) { + dataTypes.add(dt4); + } + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/LRUCache.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/LRUCache.java new file mode 100644 index 0000000000..34a82fd2d3 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/LRUCache.java @@ -0,0 +1,88 @@ +/* + * 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.databinding.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A Simple LRU Cache + * + * @version $Revision$ + * @param <K> + * @param <V> + */ + +public class LRUCache<K, V> extends LinkedHashMap<K, V> { + private static final long serialVersionUID = -342098639681884413L; + protected int maxCacheSize = 4096; + + /** + * Default constructor for an LRU Cache The default capacity is 10000 + */ + public LRUCache() { + this(0, 4096, 0.75f, true); + } + + /** + * Constructs a LRUCache with a maximum capacity + * + * @param maximumCacheSize + */ + public LRUCache(int maximumCacheSize) { + this(0, maximumCacheSize, 0.75f, true); + } + + /** + * Constructs an empty <tt>LRUCache</tt> instance with the specified + * initial capacity, maximumCacheSize,load factor and ordering mode. + * + * @param initialCapacity the initial capacity. + * @param maximumCacheSize + * @param loadFactor the load factor. + * @param accessOrder the ordering mode - <tt>true</tt> for access-order, + * <tt>false</tt> for insertion-order. + * @throws IllegalArgumentException if the initial capacity is negative or + * the load factor is non-positive. + */ + + public LRUCache(int initialCapacity, int maximumCacheSize, float loadFactor, boolean accessOrder) { + super(initialCapacity, loadFactor, accessOrder); + this.maxCacheSize = maximumCacheSize; + } + + /** + * @return Returns the maxCacheSize. + */ + public int getMaxCacheSize() { + return maxCacheSize; + } + + /** + * @param maxCacheSize The maxCacheSize to set. + */ + public void setMaxCacheSize(int maxCacheSize) { + this.maxCacheSize = maxCacheSize; + } + + @Override + protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { + return size() > maxCacheSize; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java new file mode 100644 index 0000000000..3423d3e3b0 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java @@ -0,0 +1,296 @@ +/* + * 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.databinding.xml; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; + +/** + * @version $Rev$ $Date$ + */ +public class BeanXMLStreamReaderImpl extends XmlTreeStreamReaderImpl { + private static final Comparator<Accessor> COMPARATOR = new Comparator<Accessor>() { + public int compare(Accessor o1, Accessor o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + public static class BeanXmlNodeImpl extends SimpleXmlNodeImpl implements XmlNode { + private static final Object[] NULL = null; + private static final SimpleTypeMapperImpl MAPPER = new SimpleTypeMapperImpl(); + + public BeanXmlNodeImpl(Object bean) { + super(getName(bean == null ? null : bean.getClass()), bean); + } + + public BeanXmlNodeImpl(QName name, Object bean) { + super(name, bean); + } + + private static boolean isSimpleType(Class<?> javaType) { + return SimpleTypeMapperImpl.getXMLType(javaType) != null; + } + + private static String getStringValue(Object o) { + if (o == null) { + return null; + } + TypeInfo info = SimpleTypeMapperImpl.getXMLType(o.getClass()); + if (info != null) { + return MAPPER.toXMLLiteral(info.getQName(), o, null); + } else { + return String.valueOf(o); + } + } + + @Override + public Iterator<XmlNode> children() { + if (name == null) { + return null; + } + if (value == null) { + return super.children(); + } + if (isSimpleType(value.getClass())) { + XmlNode textNode = new BeanXmlNodeImpl(null, value); + return Arrays.asList(textNode).iterator(); + } + if (Map.class.isAssignableFrom(value.getClass())) { + List<XmlNode> entries = new ArrayList<XmlNode>(); + QName entryName = new QName(name.getNamespaceURI(), "entry"); + Map map = (Map)value; + if (map != null) { + for (Object e : map.entrySet()) { + Map.Entry entry = (Map.Entry)e; + entries.add(new BeanXmlNodeImpl(entryName, entry)); + } + } + return entries.iterator(); + } + try { + Map<String, Accessor> accessorMap = getAccessors(value); + List<Accessor> accessorList = new ArrayList<Accessor>(accessorMap.values()); + Collections.sort(accessorList, COMPARATOR); + + List<XmlNode> props = new ArrayList<XmlNode>(); + for (Accessor accessor : accessorList) { + Class<?> pType = accessor.getType(); + + QName pName = new QName(name.getNamespaceURI(), accessor.getName()); + Object pValue = accessor.getValue(); + if (pType.isArray()) { + if (pValue != null) { + int i1 = Array.getLength(pValue); + for (int j = 0; j < i1; j++) { + Object o = Array.get(pValue, j); + props.add(new BeanXmlNodeImpl(pName, o)); + } + } else { + // TODO: How to handle null? + } + } else if (Collection.class.isAssignableFrom(pType)) { + Collection objList = (Collection)pValue; + if (objList != null && objList.size() > 0) { + for (Iterator j = objList.iterator(); j.hasNext();) { + Object o = j.next(); + props.add(new BeanXmlNodeImpl(pName, o)); + } + + } else { + // How to handle null + } + } else { + props.add(new BeanXmlNodeImpl(pName, pValue)); + } + } + return props.iterator(); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public QName getName() { + return name; + } + + @Override + public String getValue() { + return getStringValue(value); + } + + private static String getPackageName(Class<?> cls) { + String name = cls.getName(); + int index = name.lastIndexOf('.'); + return index == -1 ? "" : name.substring(0, index); + } + + public static QName getName(Class<?> cls) { + if (cls == null) { + return null; + } + + String packageName = getPackageName(cls); + + if ("".equals(packageName)) { + return new QName("", cls.getSimpleName()); + } + StringBuffer ns = new StringBuffer("http://"); + String[] names = packageName.split("\\."); + for (int i = names.length - 1; i >= 0; i--) { + ns.append(names[i]); + if (i != 0) { + ns.append('.'); + } + } + ns.append('/'); + return new QName(ns.toString(), cls.getSimpleName()); + } + + } + + public BeanXMLStreamReaderImpl(QName name, Object bean) { + super(getXmlNode(name, bean)); + } + + private static BeanXmlNodeImpl getXmlNode(QName name, Object bean) { + BeanXmlNodeImpl root = null; + if (name != null) { + root = new BeanXmlNodeImpl(name, bean); + } else { + root = new BeanXmlNodeImpl(bean); + } + return root; + } + + public static interface Accessor { + String getName(); + + Class<?> getType(); + + Object getValue() throws Exception; + + void setValue(Object value) throws Exception; + } + + private static class FieldAccessor implements Accessor { + private Object target; + private Field field; + + public FieldAccessor(Object target, Field field) { + super(); + this.target = target; + this.field = field; + this.field.setAccessible(true); + } + + public String getName() { + return field.getName(); + } + + public Object getValue() throws Exception { + return field.get(target); + } + + public void setValue(Object value) throws Exception { + field.set(target, value); + } + + public Class<?> getType() { + return field.getType(); + } + + } + + private static class PropertyAccessor implements Accessor { + private Object target; + private PropertyDescriptor prop; + + public PropertyAccessor(Object target, PropertyDescriptor prop) { + super(); + this.target = target; + this.prop = prop; + } + + public String getName() { + return prop.getName(); + } + + public Class<?> getType() { + return prop.getPropertyType(); + } + + public Object getValue() throws Exception { + Method getter = prop.getReadMethod(); + if (getter != null) { + getter.setAccessible(true); + return getter.invoke(target); + } + throw new IllegalAccessException("The property cannot be read: " + getName()); + } + + public void setValue(Object value) throws Exception { + Method setter = prop.getWriteMethod(); + if (setter != null) { + setter.setAccessible(true); + setter.invoke(target); + } + throw new IllegalAccessException("The property cannot be written: " + getName()); + } + + } + + private static Map<String, Accessor> getAccessors(Object target) throws Exception { + if (target == null) { + return Collections.emptyMap(); + } + Map<String, Accessor> map = new HashMap<String, Accessor>(); + Class<?> type = target.getClass(); + for (Field f : type.getFields()) { + map.put(f.getName(), new FieldAccessor(target, f)); + } + BeanInfo info = Introspector.getBeanInfo(type, Object.class); + for (PropertyDescriptor p : info.getPropertyDescriptors()) { + // if (p.getReadMethod() != null && p.getWriteMethod() != null) { + map.put(p.getName(), new PropertyAccessor(target, p)); + // } + } + return map; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java new file mode 100644 index 0000000000..92058d769f --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java @@ -0,0 +1,72 @@ +/* + * 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.databinding.xml; + + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Node; + +/** + * DOM DataBinding + * + * @version $Rev$ $Date$ + */ +public class DOMDataBinding extends BaseDataBinding { + public static final String NAME = Node.class.getName(); + public static final String[] ALIASES = new String[] {"dom"}; + + public static final String ROOT_NAMESPACE = "http://tuscany.apache.org/xmlns/sca/databinding/dom/1.0"; + public static final QName ROOT_ELEMENT = new QName(ROOT_NAMESPACE, "root"); + + public DOMDataBinding() { + super(NAME, ALIASES, Node.class); + } + + @Override + public WrapperHandler getWrapperHandler() { + return new DOMWrapperHandler(); + } + + @Override + public Object copy(Object source, DataType dataType, Operation operation) { + if (Node.class.isAssignableFrom(source.getClass())) { + Node nodeSource = (Node)source; + return nodeSource.cloneNode(true); + } + return super.copy(source, dataType, operation); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (Node.class.isAssignableFrom(type.getPhysical())) { + if (type.getLogical() == null) { + type.setLogical(new XMLType(ROOT_ELEMENT, null)); + } + type.setDataBinding(NAME); + return true; + } + return false; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java new file mode 100644 index 0000000000..9e1ebb3522 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java @@ -0,0 +1,141 @@ +/* + * 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.databinding.xml; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class DOMWrapperHandler implements WrapperHandler<Node> { + + public DOMWrapperHandler() { + super(); + } + + public Node create(Operation operation, boolean input) { + try { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + // Class<?> wrapperClass = input ? wrapperInfo.getInputWrapperClass() : wrapperInfo.getOutputWrapperClass(); + Document document = DOMHelper.newDocument(); + QName name = element.getQName(); + return DOMHelper.createElement(document, name); + } catch (ParserConfigurationException e) { + throw new TransformationException(e); + } + } + + public void setChildren(Node wrapper, + Object[] childObjects, + Operation operation, boolean input) { + List<ElementInfo> childElements = input? operation.getWrapper().getInputChildElements(): + operation.getWrapper().getOutputChildElements(); + for (int i = 0; i < childElements.size(); i++) { + setChild(wrapper, i, childElements.get(i), childObjects[i]); + } + + } + public void setChild(Node wrapper, int i, ElementInfo childElement, Object value) { + Node node = (Node)value; + if (node.getNodeType() == Node.DOCUMENT_NODE) { + node = ((Document)node).getDocumentElement(); + } + wrapper.appendChild(wrapper.getOwnerDocument().importNode(node, true)); + } + + public List getChildren(Node wrapper, Operation operation, boolean input) { + assert wrapper != null; + List<ElementInfo> childElements = input? operation.getWrapper().getInputChildElements(): + operation.getWrapper().getOutputChildElements(); + if (wrapper.getNodeType() == Node.DOCUMENT_NODE) { + wrapper = ((Document)wrapper).getDocumentElement(); + } + List<Node> elements = new ArrayList<Node>(); + NodeList nodes = wrapper.getChildNodes(); + for (int j = 0; j < nodes.getLength(); j++) { + Node node = nodes.item(j); + if (node.getNodeType() == Node.ELEMENT_NODE) { + elements.add(node); + } + } + return elements; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getWrapperType(Operation, boolean) + */ + public DataType getWrapperType(Operation operation, boolean input) { + WrapperInfo wrapper = operation.getWrapper(); + ElementInfo element = input? wrapper.getInputWrapperElement(): wrapper.getOutputWrapperElement(); + DataType<XMLType> wrapperType = + new DataTypeImpl<XMLType>(DOMDataBinding.NAME, Node.class, new XMLType(element)); + return wrapperType; + } + + public boolean isInstance(Object wrapperObj, + Operation operation, + boolean input) { + WrapperInfo wrapperInfo = operation.getWrapper(); + ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement(); + List<ElementInfo> childElements = + input ? wrapperInfo.getInputChildElements() : wrapperInfo.getOutputChildElements(); + Node wrapper = (Node)wrapperObj; + if (wrapper.getNodeType() == Node.DOCUMENT_NODE) { + wrapper = ((Document)wrapper).getDocumentElement(); + } + QName elementName = new QName(wrapper.getNamespaceURI(), wrapper.getLocalName()); + if (!element.getQName().equals(elementName)) { + return false; + } + Set<QName> names = new HashSet<QName>(); + for (ElementInfo e : childElements) { + names.add(e.getQName()); + } + NodeList nodes = wrapper.getChildNodes(); + for (int j = 0; j < nodes.getLength(); j++) { + Node node = nodes.item(j); + if (node.getNodeType() == Node.ELEMENT_NODE) { + elementName = new QName(wrapper.getNamespaceURI(), wrapper.getLocalName()); + if (!names.contains(elementName)) { + return false; + } + } + } + return true; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXMLStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXMLStreamReader.java new file mode 100644 index 0000000000..8c7a742cdd --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXMLStreamReader.java @@ -0,0 +1,36 @@ +/* + * 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.databinding.xml; + +import org.w3c.dom.Node; + +public class DOMXMLStreamReader extends XmlTreeStreamReaderImpl { + + public DOMXMLStreamReader(Node node) { + super(new DOMXmlNodeImpl(node)); + switch (node.getNodeType()) { + case Node.DOCUMENT_NODE: + break; + case Node.ELEMENT_NODE: + break; + default: + throw new IllegalArgumentException("Illegal node type: " + node); + } + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXmlNodeImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXmlNodeImpl.java new file mode 100644 index 0000000000..507c141c33 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXmlNodeImpl.java @@ -0,0 +1,156 @@ +/* + * 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.databinding.xml; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @version $Rev$ $Date$ + */ +public class DOMXmlNodeImpl implements XmlNode { + private Node node; + private Map<String, String> namespaces; + private Type type; + + /** + * @param element + */ + public DOMXmlNodeImpl(Node element) { + super(); + if (element.getNodeType() == Node.DOCUMENT_NODE) { + this.node = ((Document)element).getDocumentElement(); + } else { + this.node = element; + } + switch (node.getNodeType()) { + case Node.CDATA_SECTION_NODE: + this.type = Type.CHARACTERS; + break; + case Node.ELEMENT_NODE: + this.type = Type.ELEMENT; + break; + case Node.TEXT_NODE: + this.type = Type.CHARACTERS; + break; + } + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#attributes() + */ + public List<XmlNode> attributes() { + if (type != Type.ELEMENT) { + return null; + } + NamedNodeMap attrs = node.getAttributes(); + List<XmlNode> xmlAttrs = new ArrayList<XmlNode>(); + for (int i = 0; i < attrs.getLength(); i++) { + Attr attr = (Attr)attrs.item(i); + if (!attr.getName().equals("xmlns") && !attr.getName().startsWith("xmlns:")) { + xmlAttrs.add(new SimpleXmlNodeImpl(getQName(attr), attr.getValue(), XmlNode.Type.ATTRIBUTE)); + } + } + return xmlAttrs; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#children() + */ + public Iterator<XmlNode> children() { + if (type != Type.ELEMENT) { + return null; + } + NodeList nodes = node.getChildNodes(); + List<XmlNode> xmlNodes = new ArrayList<XmlNode>(); + for (int i = 0; i < nodes.getLength(); i++) { + Node child = (Node)nodes.item(i); + int nodeType = child.getNodeType(); + if (nodeType == Node.ELEMENT_NODE || nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + xmlNodes.add(new DOMXmlNodeImpl(child)); + } + } + return xmlNodes.iterator(); + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getName() + */ + public QName getName() { + return getQName(node); + } + + private static QName getQName(Node node) { + int type = node.getNodeType(); + if (type == Node.ELEMENT_NODE || type == Node.ATTRIBUTE_NODE) { + String ns = node.getNamespaceURI(); + String prefix = node.getPrefix(); + String localName = node.getLocalName(); + return new QName(ns == null ? "" : ns, localName, prefix == null ? "" : prefix); + } + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getValue() + */ + public String getValue() { + return node.getNodeValue(); + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#namespaces() + */ + public Map<String, String> namespaces() { + if (type != Type.ELEMENT) { + return null; + } + if (namespaces == null) { + namespaces = new HashMap<String, String>(); + NamedNodeMap attrs = node.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + Attr attr = (Attr)attrs.item(i); + if ("xmlns".equals(attr.getPrefix())) { + namespaces.put(attr.getLocalName(), attr.getValue()); + } + if ("xmlns".equals(attr.getName())) { + namespaces.put("", attr.getValue()); + } + } + } + return namespaces; + } + + public Type getType() { + return type; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DelegatingNamespaceContext.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DelegatingNamespaceContext.java new file mode 100644 index 0000000000..7f49a50e1e --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DelegatingNamespaceContext.java @@ -0,0 +1,310 @@ +/* + * 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.databinding.xml; + +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.Iterator; +import java.util.List; + +import javax.xml.namespace.NamespaceContext; + +public class DelegatingNamespaceContext implements NamespaceContext { + private static int count; + + private class WrappingIterator implements Iterator { + + private Iterator containedIterator; + + public WrappingIterator(Iterator containedIterator) { + this.containedIterator = containedIterator; + } + + public Iterator getContainedIterator() { + return containedIterator; + } + + public boolean hasNext() { + return containedIterator.hasNext(); + } + + public Object next() { + return containedIterator.next(); + } + + /** + * As per the contract on the API of Namespace context the returned iterator should be immutable + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + public void setContainedIterator(Iterator containedIterator) { + this.containedIterator = containedIterator; + } + } + + private NamespaceContext parentNsContext; + + private FastStack<String> prefixStack = new FastStack<String>(); + + // Keep two ArrayLists for the prefixes and namespaces. They should be in + // sync + // since the index of the entry will be used to relate them + // use the minimum initial capacity to let things handle memory better + + private FastStack<String> uriStack = new FastStack<String>(); + + /** + * Generates a unique namespace prefix that is not in the scope of the NamespaceContext + * + * @return string + */ + public String generateUniquePrefix() { + String prefix = "p" + count++; + // null should be returned if the prefix is not bound! + while (getNamespaceURI(prefix) != null) { + prefix = "p" + count++; + } + + return prefix; + } + + public String getNamespaceURI(String prefix) { + // do the corrections as per the Javadoc + int index = prefixStack.search(prefix); + if (index != -1) { + return uriStack.get(index); + } + if (parentNsContext != null) { + return parentNsContext.getPrefix(prefix); + } + return null; + } + + public NamespaceContext getParentNsContext() { + return parentNsContext; + } + + public String getPrefix(String uri) { + // do the corrections as per the Javadoc + int index = uriStack.search(uri); + if (index != -1) { + return prefixStack.get(index); + } + + if (parentNsContext != null) { + return parentNsContext.getPrefix(uri); + } + return null; + } + + public Iterator getPrefixes(String uri) { + // create an ArrayList that contains the relevant prefixes + String[] uris = uriStack.toArray(new String[uriStack.size()]); + List<String> tempList = new ArrayList<String>(); + for (int i = uris.length - 1; i >= 0; i--) { + if (uris[i].equals(uri)) { + tempList.add(prefixStack.get(i)); + // we assume that array conversion preserves the order + } + } + // by now all the relevant prefixes are collected + // make a new iterator and provide a wrapper iterator to + // obey the contract on the API + return new WrappingIterator(tempList.iterator()); + } + + /** + * Pop a namespace + */ + public void popNamespace() { + prefixStack.pop(); + uriStack.pop(); + } + + /** + * Register a namespace in this context + * + * @param prefix + * @param uri + */ + public void pushNamespace(String prefix, String uri) { + prefixStack.push(prefix); + uriStack.push(uri); + + } + + public void setParentNsContext(NamespaceContext parentNsContext) { + this.parentNsContext = parentNsContext; + } + + /** + * An implementation of the {@link java.util.Stack} API that is based on an <code>ArrayList</code> instead of a + * <code>Vector</code>, so it is not synchronized to protect against multi-threaded access. The implementation is + * therefore operates faster in environments where you do not need to worry about multiple thread contention. + * <p> + * The removal order of an <code>ArrayStack</code> is based on insertion order: The most recently added element is + * removed first. The iteration order is <i>not</i> the same as the removal order. The iterator returns elements + * from the bottom up, whereas the {@link #remove()} method removes them from the top down. + * <p> + * Unlike <code>Stack</code>, <code>ArrayStack</code> accepts null entries. + */ + public static class FastStack<T> extends ArrayList<T> { + + /** Ensure Serialization compatibility */ + private static final long serialVersionUID = 2130079159931574599L; + + /** + * Constructs a new empty <code>ArrayStack</code>. The initial size is controlled by <code>ArrayList</code> + * and is currently 10. + */ + public FastStack() { + super(); + } + + /** + * Constructs a new empty <code>ArrayStack</code> with an initial size. + * + * @param initialSize the initial size to use + * @throws IllegalArgumentException if the specified initial size is negative + */ + public FastStack(int initialSize) { + super(initialSize); + } + + /** + * Return <code>true</code> if this stack is currently empty. + * <p> + * This method exists for compatibility with <code>java.util.Stack</code>. New users of this class should use + * <code>isEmpty</code> instead. + * + * @return true if the stack is currently empty + */ + public boolean empty() { + return isEmpty(); + } + + /** + * Returns the top item off of this stack without removing it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T peek() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return get(n - 1); + } + } + + /** + * Returns the n'th item down (zero-relative) from the top of this stack without removing it. + * + * @param n the number of items down to go + * @return the n'th item on the stack, zero relative + * @throws EmptyStackException if there are not enough items on the stack to satisfy this request + */ + public T peek(int n) throws EmptyStackException { + int m = (size() - n) - 1; + if (m < 0) { + throw new EmptyStackException(); + } else { + return get(m); + } + } + + /** + * Pops the top item off of this stack and return it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T pop() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return remove(n - 1); + } + } + + /** + * Pushes a new item onto the top of this stack. The pushed item is also returned. This is equivalent to calling + * <code>add</code>. + * + * @param item the item to be added + * @return the item just pushed + */ + public Object push(T item) { + add(item); + return item; + } + + /** + * Returns the top-most index for the object in the stack + * + * @param object the object to be searched for + * @return top-most index, or -1 if not found + */ + public int search(T object) { + int i = size() - 1; // Current index + while (i >= 0) { + T current = get(i); + if ((object == null && current == null) || (object != null && object.equals(current))) { + return i; + } + i--; + } + return -1; + } + + /** + * Returns the element on the top of the stack. + * + * @return the element on the top of the stack + * @throws EmptyStackException if the stack is empty + */ + public T get() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return get(size - 1); + } + + /** + * Removes the element on the top of the stack. + * + * @return the removed element + * @throws EmptyStackException if the stack is empty + */ + public T remove() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return remove(size - 1); + } + + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java new file mode 100644 index 0000000000..5f583da283 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java @@ -0,0 +1,67 @@ +/* + * 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.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + * + * @version $Rev$ $Date$ + */ +public class InputSource2Node extends BaseTransformer<InputSource, Node> implements + PullTransformer<InputSource, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputSource source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source.getCharacterStream()); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputSource> getSourceType() { + return InputSource.class; + } + + @Override + public Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java new file mode 100644 index 0000000000..39116ba4a1 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.xml; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputSource to SAX + * + * @version $Rev$ $Date$ + */ +public class InputSource2SAX extends BaseTransformer<InputSource, ContentHandler> implements + PushTransformer<InputSource, ContentHandler> { + + public void transform(InputSource source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setFeature("http://xml.org/sax/features/namespaces", true); + reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false); + reader.setContentHandler(target); + reader.parse(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputSource> getSourceType() { + return InputSource.class; + } + + @Override + public Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java new file mode 100644 index 0000000000..e40c3006fb --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java @@ -0,0 +1,69 @@ +/* + * 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.databinding.xml; + +import java.io.InputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + * + * @version $Rev$ $Date$ + */ +public class InputStream2Node extends BaseTransformer<InputStream, Node> implements + PullTransformer<InputStream, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputStream source, TransformationContext context) { + try { + Source streamSource = new SAXSource(new InputSource(source)); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + public Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java new file mode 100644 index 0000000000..3b7bd3088a --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java @@ -0,0 +1,64 @@ +/* + * 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.databinding.xml; + +import java.io.InputStream; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputStream to SAX + * + * @version $Rev$ $Date$ + */ +public class InputStream2SAX extends BaseTransformer<InputStream, ContentHandler> implements + PushTransformer<InputStream, ContentHandler> { + public void transform(InputStream source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setContentHandler(target); + reader.parse(new InputSource(source)); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + public Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValueArrayStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValueArrayStreamReader.java new file mode 100644 index 0000000000..5a31d9db91 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValueArrayStreamReader.java @@ -0,0 +1,403 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +public class NameValueArrayStreamReader implements XMLFragmentStreamReader { + + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 1; + private static final int END_ELEMENT_STATE = 2; + private static final int FINAL_END_ELEMENT_STATE = 3; + private static final int START_ELEMENT_STATE_WITH_NULL = 4; + + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + // the index of the array + private int arrayIndex; + + private QName name; + private String[] values; + + // start element is the default state + private int state = START_ELEMENT_STATE; + + public NameValueArrayStreamReader(QName name, String[] values) { + this.name = name; + this.values = values; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + this.namespaceContext.setParentNsContext(nsContext); + } + + public void init() { + // TODO what if the QName namespace has not been declared + } + + public Object getProperty(String string) throws IllegalArgumentException { + return null; + } + + /** + * @throws XMLStreamException + */ + public int next() throws XMLStreamException { + switch (state) { + case START_ELEMENT_STATE: + if (values.length > 0) { + state = TEXT_STATE; + return CHARACTERS; + } else { + state = FINAL_END_ELEMENT_STATE; + return END_ELEMENT; + } + + case START_ELEMENT_STATE_WITH_NULL: + if (arrayIndex == (values.length - 1)) { + state = FINAL_END_ELEMENT_STATE; + } else { + state = END_ELEMENT_STATE; + } + return END_ELEMENT; + case FINAL_END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case END_ELEMENT_STATE: + // we've to have more values since this is not the + // last value + // increment the counter + arrayIndex++; + if (values[arrayIndex] == null) { + state = START_ELEMENT_STATE_WITH_NULL; + } else { + state = START_ELEMENT_STATE; + } + return START_ELEMENT; + case TEXT_STATE: + if (arrayIndex == (values.length - 1)) { + state = FINAL_END_ELEMENT_STATE; + return END_ELEMENT; + } else { + state = END_ELEMENT_STATE; + return END_ELEMENT; + } + + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // nothing done here + } + + public String getElementText() throws XMLStreamException { + return null; // not implemented + } + + public int nextTag() throws XMLStreamException { + return 0; // not implemented + } + + public String getAttributeValue(String string, String string1) { + if (state == TEXT_STATE) { + // TODO something + return null; + } else { + return null; + } + + } + + public int getAttributeCount() { + if (state == START_ELEMENT_STATE_WITH_NULL) { + return 1; + } + if (state == START_ELEMENT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + + } + + public QName getAttributeName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getNamespaceURI(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getLocalPart(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getPrefix(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not implemented + } + + public String getAttributeValue(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_VALUE_TRUE; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + public int getNamespaceCount() { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent()) { + return 1; + } else { + return 0; + } + + } + + public String getNamespacePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return NIL_QNAME.getPrefix(); + } else { + return null; + } + } + + public String getNamespaceURI(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return NIL_QNAME.getNamespaceURI(); + } else { + return null; + } + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public boolean isDone() { + return state == FINAL_END_ELEMENT_STATE; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + case FINAL_END_ELEMENT_STATE: + return END_ELEMENT; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getText() { + if (state == TEXT_STATE) { + return values[arrayIndex]; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return values[arrayIndex].toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return values[arrayIndex].length(); + } else { + throw new IllegalStateException(); + } + + } + + public String getEncoding() { + return null; + } + + public boolean hasText() { + return state == TEXT_STATE; + } + + public Location getLocation() { + return null; // not supported + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public boolean hasName() { + return state != TEXT_STATE; + + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public String getVersion() { + return null; // TODO 1.0 ? + } + + public boolean isStandalone() { + return false; + } + + public boolean standaloneSet() { + return false; + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPIData() { + return null; + } + + public boolean hasNext() throws XMLStreamException { + return state != FINAL_END_ELEMENT_STATE; + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + return state == START_ELEMENT_STATE; + } + + public boolean isEndElement() { + return state == END_ELEMENT_STATE; + } + + public boolean isCharacters() { + return state == TEXT_STATE; + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + /** + * Test whether the xsi namespace is present + */ + private boolean isXsiNamespacePresent() { + return namespaceContext.getNamespaceURI(NIL_QNAME.getPrefix()) != null; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValuePairStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValuePairStreamReader.java new file mode 100644 index 0000000000..fdc3c4139b --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValuePairStreamReader.java @@ -0,0 +1,347 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + + +public class NameValuePairStreamReader implements XMLFragmentStreamReader { + + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 1; + private static final int END_ELEMENT_STATE = 2; + + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + + private QName name; + private String value; + + private int state = START_ELEMENT_STATE; + // initiate at the start element state + + // keeps track whether the namespace is declared + // false by default + private boolean nsDeclared; + + public NameValuePairStreamReader(QName name, String value) { + this.name = name; + this.value = value; + } + + public Object getProperty(String key) throws IllegalArgumentException { + return null; + } + + public int next() throws XMLStreamException { + // no need to handle null here. it should have been handled + // already + switch (state) { + case START_ELEMENT_STATE: + state = TEXT_STATE; + return CHARACTERS; + case END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case TEXT_STATE: + state = END_ELEMENT_STATE; + return END_ELEMENT; + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // not implemented + } + + public String getElementText() throws XMLStreamException { + if (state == START_ELEMENT) { + // move to the end state and return the value + state = END_ELEMENT_STATE; + return value; + } else { + throw new XMLStreamException(); + } + + } + + public int nextTag() throws XMLStreamException { + return 0; // TODO + } + + public boolean hasNext() throws XMLStreamException { + return state != END_ELEMENT_STATE; + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + return state == START_ELEMENT_STATE; + } + + public boolean isEndElement() { + return state == END_ELEMENT_STATE; + } + + public boolean isCharacters() { + return state == TEXT_STATE; + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + public String getAttributeValue(String string, String string1) { + return null; + } + + public int getAttributeCount() { + return 0; + } + + public QName getAttributeName(int i) { + return null; + } + + public String getAttributeNamespace(int i) { + return null; + } + + public String getAttributeLocalName(int i) { + return null; + } + + public String getAttributePrefix(int i) { + return null; + } + + public String getAttributeType(int i) { + return null; + } + + public String getAttributeValue(int i) { + return null; + } + + public boolean isAttributeSpecified(int i) { + return false; // no attributes here + } + + public int getNamespaceCount() { + return nsDeclared ? 1 : 0; + } + + public String getNamespacePrefix(int i) { + return (nsDeclared && i == 0) ? name.getPrefix() : null; + } + + public String getNamespaceURI(int i) { + return (nsDeclared && i == 0) ? name.getNamespaceURI() : null; + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getText() { + if (state == TEXT_STATE) { + return value; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return value.toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return value.length(); + } else { + throw new IllegalStateException(); + } + + } + + public String getEncoding() { + return null; + } + + public boolean hasText() { + return state == TEXT_STATE; + } + + public Location getLocation() { + return new Location() { + public int getLineNumber() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getCharacterOffset() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public boolean hasName() { + return state != TEXT_STATE; + + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public String getVersion() { + return null; // TODO 1.0 ? + } + + public boolean isStandalone() { + return false; + } + + public boolean standaloneSet() { + return false; + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPIData() { + return null; + } + + public boolean isDone() { + return state == END_ELEMENT_STATE; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + this.namespaceContext.setParentNsContext(nsContext); + } + + public void init() { + // just add the current elements namespace and prefix to the this + // elements nscontext + addToNsMap(name.getPrefix(), name.getNamespaceURI()); + + } + + /** + * @param prefix + * @param uri + */ + private void addToNsMap(String prefix, String uri) { + // TODO - need to fix this up to cater for cases where + // namespaces are having no prefixes + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + // this namespace is not there. Need to declare it + namespaceContext.pushNamespace(prefix, uri); + nsDeclared = true; + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NamedProperty.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NamedProperty.java new file mode 100644 index 0000000000..04d7d65a0d --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NamedProperty.java @@ -0,0 +1,59 @@ +/* + * 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.databinding.xml; + +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * A named property + * + * @version $Rev$ $Date$ + */ +public class NamedProperty implements Map.Entry<QName, Object> { + private QName key; + + private Object value; + + public NamedProperty(QName key, Object value) { + this.key = key; + this.value = value; + } + + public NamedProperty(String key, Object value) { + this.key = new QName(key); + this.value = value; + } + + public QName getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object value) { + Object v = this.value; + this.value = value; + return v; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NilElementStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NilElementStreamReader.java new file mode 100644 index 0000000000..abc4bf3785 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NilElementStreamReader.java @@ -0,0 +1,279 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +public class NilElementStreamReader implements XMLFragmentStreamReader { + + private static final int END_ELEMENT_STATE = 2; + + private static final int START_ELEMENT_STATE = 1; + private int currentState = START_ELEMENT; + + private QName elementQName; + + public NilElementStreamReader(QName elementQName) { + this.elementQName = elementQName; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // NOOP + } + + public void close() throws XMLStreamException { + // do nothing + } + + public int getAttributeCount() { + return 1; + } + + public String getAttributeLocalName(int i) { + return (i == 0) ? NIL_QNAME.getLocalPart() : null; + } + + public QName getAttributeName(int i) { + return (i == 0) ? NIL_QNAME : null; + } + + public String getAttributeNamespace(int i) { + return (i == 0) ? NIL_QNAME.getNamespaceURI() : null; + } + + public String getAttributePrefix(int i) { + return (i == 0) ? NIL_QNAME.getPrefix() : null; + } + + public String getAttributeType(int i) { + throw new UnsupportedOperationException(); + } + + public String getAttributeValue(int i) { + return (i == 0) ? NIL_VALUE_TRUE : null; + } + + public String getAttributeValue(String string, String string1) { + if (string == null && NIL_QNAME.getLocalPart().equals(string1)) { + return NIL_VALUE_TRUE; + } + return null; + } + + public String getCharacterEncodingScheme() { + throw new UnsupportedOperationException(); + } + + public String getElementText() throws XMLStreamException { + return null; + } + + public String getEncoding() { + return null; + } + + public int getEventType() { + int returnEvent = START_DOCUMENT; + switch (currentState) { + case START_ELEMENT_STATE: + returnEvent = START_ELEMENT; + break; + case END_ELEMENT_STATE: + returnEvent = END_ELEMENT; + break; + } + return returnEvent; + } + + public String getLocalName() { + return elementQName.getLocalPart(); + } + + public Location getLocation() { + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + return elementQName; + } + + public NamespaceContext getNamespaceContext() { + throw new UnsupportedOperationException(); + } + + public int getNamespaceCount() { + return 0; + } + + public String getNamespacePrefix(int i) { + return null; + } + + public String getNamespaceURI() { + return elementQName.getNamespaceURI(); + } + + public String getNamespaceURI(int i) { + return null; + } + + public String getNamespaceURI(String string) { + if (elementQName.getPrefix() != null && elementQName.getPrefix().equals(string)) { + return elementQName.getNamespaceURI(); + } else { + return null; + } + } + + public String getPIData() { + throw new UnsupportedOperationException(); + } + + public String getPITarget() { + throw new UnsupportedOperationException(); + } + + public String getPrefix() { + return elementQName.getPrefix(); + } + + public Object getProperty(String key) throws IllegalArgumentException { + // since optimization is a global property + // we've to implement it everywhere + return null; + } + + public String getText() { + return null; + } + + public char[] getTextCharacters() { + return new char[0]; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + return 0; + } + + public int getTextLength() { + return 0; + } + + public int getTextStart() { + return 0; + } + + public String getVersion() { + throw new UnsupportedOperationException(); + } + + public boolean hasName() { + return true; + } + + public boolean hasNext() throws XMLStreamException { + return currentState != END_ELEMENT_STATE; + + } + + public boolean hasText() { + return false; + } + + public void init() { + // NOOP + } + + public boolean isAttributeSpecified(int i) { + return i == 0; + } + + public boolean isCharacters() { + return false; + } + + public boolean isDone() { + return currentState == END_ELEMENT_STATE; + } + + public boolean isEndElement() { + return currentState == END_ELEMENT_STATE; + } + + public boolean isStandalone() { + throw new UnsupportedOperationException(); + } + + public boolean isStartElement() { + return currentState == START_ELEMENT_STATE; + } + + public boolean isWhiteSpace() { + return false; + } + + public int next() throws XMLStreamException { + int returnEvent = START_DOCUMENT; + switch (currentState) { + case START_ELEMENT_STATE: + currentState = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + break; + case END_ELEMENT_STATE: + throw new XMLStreamException("parser completed!"); + + } + return returnEvent; + } + + public int nextTag() throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // nothing + } + + public boolean standaloneSet() { + throw new UnsupportedOperationException(); + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java new file mode 100644 index 0000000000..5500d0bcca --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java @@ -0,0 +1,68 @@ +/* + * 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.databinding.xml; + +import java.io.OutputStream; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Push DOM Node to OutputStream + * + * @version $Rev$ $Date$ + */ +public class Node2OutputStream extends BaseTransformer<Node, OutputStream> implements + PushTransformer<Node, OutputStream> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, OutputStream writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<OutputStream> getTargetType() { + return OutputStream.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java new file mode 100644 index 0000000000..d5bf7e76b5 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java @@ -0,0 +1,45 @@ +/* + * 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.databinding.xml; + +import org.apache.tuscany.sca.databinding.impl.SimpleType2JavaTransformer; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transformer to convert data from a simple java Object to OMElement. + * + * @version $Rev$ $Date$ + */ +public class Node2SimpleJavaType extends SimpleType2JavaTransformer<Node> { + + @Override + protected String getText(Node source) { + if (source instanceof Document) { + source = ((Document)source).getDocumentElement(); + } + return source.getTextContent(); + + } + + @Override + public Class getSourceType() { + return Node.class; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java new file mode 100644 index 0000000000..3c9022bc3c --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java @@ -0,0 +1,61 @@ +/* + * 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.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Transform TrAX Node to Source + * + * @version $Rev$ $Date$ + */ +public class Node2SourceTransformer extends BaseTransformer<Node, Source> implements + PullTransformer<Node, Source> { + + public Source transform(Node source, TransformationContext context) { + try { + return new DOMSource(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<Source> getTargetType() { + return Source.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2String.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2String.java new file mode 100644 index 0000000000..1b54b1fd1e --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2String.java @@ -0,0 +1,62 @@ +/* + * 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.databinding.xml; + +import java.io.StringWriter; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML String + * + * @version $Rev$ $Date$ + */ +public class Node2String extends BaseTransformer<Node, String> implements PullTransformer<Node, String> { + private static final Node2Writer TRANSFORMER = new Node2Writer(); + + public String transform(Node source, TransformationContext context) { + try { + StringWriter writer = new StringWriter(); + TRANSFORMER.transform(source, writer, context); + return writer.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<Node> getSourceType() { + return Node.class; + } + + @Override + public Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2Writer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2Writer.java new file mode 100644 index 0000000000..c9631595dc --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2Writer.java @@ -0,0 +1,67 @@ +/* + * 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.databinding.xml; + +import java.io.Writer; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Push DOM Node to Writer + * + * @version $Rev$ $Date$ + */ +public class Node2Writer extends BaseTransformer<Node, Writer> implements PushTransformer<Node, Writer> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, Writer writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<Writer> getTargetType() { + return Writer.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2XMLStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2XMLStreamReader.java new file mode 100644 index 0000000000..1e8d14a151 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2XMLStreamReader.java @@ -0,0 +1,64 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML XMLStreamReader + * + * @version $Rev$ $Date$ + */ +public class Node2XMLStreamReader extends BaseTransformer<Node, XMLStreamReader> implements + PullTransformer<Node, XMLStreamReader> { + + public XMLStreamReader transform(Node source, TransformationContext context) { + if (source == null) { + return null; + } + try { + DOMXMLStreamReader reader = new DOMXMLStreamReader(source); + return reader; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2Node.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2Node.java new file mode 100644 index 0000000000..70387fa862 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2Node.java @@ -0,0 +1,67 @@ +/* + * 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.databinding.xml; + +import java.io.Reader; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Push DOM Reader to Node + * + * @version $Rev$ $Date$ + */ +public class Reader2Node extends BaseTransformer<Reader, Node> implements PullTransformer<Reader, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(Reader source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Reader> getSourceType() { + return Reader.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2SAX.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2SAX.java new file mode 100644 index 0000000000..188ecaffa3 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2SAX.java @@ -0,0 +1,60 @@ +/* + * 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.databinding.xml; + +import java.io.Reader; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + * + * @version $Rev$ $Date$ + */ +public class Reader2SAX extends BaseTransformer<Reader, ContentHandler> implements + PushTransformer<Reader, ContentHandler> { + public void transform(Reader source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(source), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Reader> getSourceType() { + return Reader.class; + } + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOM.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOM.java new file mode 100644 index 0000000000..38c61d64c8 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOM.java @@ -0,0 +1,246 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * 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.apache.tuscany.sca.databinding.xml; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; + +/** + * SAX2DOM adapter + * + * @version $Rev$ $Date$ + */ +public class SAX2DOM implements ContentHandler, LexicalHandler { + public static final String EMPTYSTRING = ""; + public static final String XML_PREFIX = "xml"; + public static final String XMLNS_PREFIX = "xmlns"; + public static final String XMLNS_STRING = "xmlns:"; + public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; + + private Node root; + + private Document document; + + private Node nextSibling; + + private Stack<Node> nodeStk = new Stack<Node>(); + + private List<String> namespaceDecls; + + private Node lastSibling; + + public SAX2DOM() throws ParserConfigurationException { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + public SAX2DOM(Node root, Node nextSibling) throws ParserConfigurationException { + this.root = root; + if (root instanceof Document) { + this.document = (Document)root; + } else if (root != null) { + this.document = root.getOwnerDocument(); + } else { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + this.nextSibling = nextSibling; + } + + public SAX2DOM(Node root) throws ParserConfigurationException { + this(root, null); + } + + public Node getDOM() { + return root; + } + + public void characters(char[] ch, int start, int length) { + final Node last = nodeStk.peek(); + + // No text nodes can be children of root (DOM006 exception) + if (last != document) { + final String text = new String(ch, start, length); + if (lastSibling != null && lastSibling.getNodeType() == Node.TEXT_NODE) { + ((Text)lastSibling).appendData(text); + } else if (last == root && nextSibling != null) { + lastSibling = last.insertBefore(document.createTextNode(text), nextSibling); + } else { + lastSibling = last.appendChild(document.createTextNode(text)); + } + + } + } + + public void startDocument() { + nodeStk.push(root); + } + + public void endDocument() { + nodeStk.pop(); + } + + public void startElement(String namespace, String localName, String qName, Attributes attrs) { + final Element tmp = document.createElementNS(namespace, qName); + + // Add namespace declarations first + if (namespaceDecls != null) { + final int nDecls = namespaceDecls.size(); + for (int i = 0; i < nDecls; i++) { + final String prefix = namespaceDecls.get(i++); + + if (prefix == null || prefix.equals(EMPTYSTRING)) { + tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX, namespaceDecls.get(i)); + } else { + tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, namespaceDecls.get(i)); + } + } + namespaceDecls.clear(); + } + + // Add attributes to element + final int nattrs = attrs.getLength(); + for (int i = 0; i < nattrs; i++) { + if (attrs.getLocalName(i) == null) { + tmp.setAttribute(attrs.getQName(i), attrs.getValue(i)); + } else { + tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), attrs.getValue(i)); + } + } + + // Append this new node onto current stack node + Node last = nodeStk.peek(); + + // If the SAX2DOM is created with a non-null next sibling node, + // insert the result nodes before the next sibling under the root. + if (last == root && nextSibling != null) { + last.insertBefore(tmp, nextSibling); + } else { + last.appendChild(tmp); + } + + // Push this node onto stack + nodeStk.push(tmp); + lastSibling = null; + } + + public void endElement(String namespace, String localName, String qName) { + nodeStk.pop(); + lastSibling = null; + } + + public void startPrefixMapping(String prefix, String uri) { + if (namespaceDecls == null) { + namespaceDecls = new ArrayList<String>(2); + } + namespaceDecls.add(prefix); + namespaceDecls.add(uri); + } + + public void endPrefixMapping(String prefix) { + // do nothing + } + + /** + * This class is only used internally so this method should never be called. + */ + public void ignorableWhitespace(char[] ch, int start, int length) { + } + + /** + * adds processing instruction node to DOM. + */ + public void processingInstruction(String target, String data) { + final Node last = nodeStk.peek(); + ProcessingInstruction pi = document.createProcessingInstruction(target, data); + if (pi != null) { + if (last == root && nextSibling != null) { + last.insertBefore(pi, nextSibling); + } else { + last.appendChild(pi); + } + + lastSibling = pi; + } + } + + /** + * This class is only used internally so this method should never be called. + */ + public void setDocumentLocator(Locator locator) { + } + + /** + * This class is only used internally so this method should never be called. + */ + public void skippedEntity(String name) { + } + + /** + * Lexical Handler method to create comment node in DOM tree. + */ + public void comment(char[] ch, int start, int length) { + final Node last = nodeStk.peek(); + Comment comment = document.createComment(new String(ch, start, length)); + if (comment != null) { + if (last == root && nextSibling != null) { + last.insertBefore(comment, nextSibling); + } else { + last.appendChild(comment); + } + + lastSibling = comment; + } + } + + // Lexical Handler methods- not implemented + public void startCDATA() { + } + + public void endCDATA() { + } + + public void startEntity(java.lang.String name) { + } + + public void endDTD() { + } + + public void endEntity(String name) { + } + + public void startDTD(String name, String publicId, String systemId) throws SAXException { + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOMPipe.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOMPipe.java new file mode 100644 index 0000000000..cb9d538389 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOMPipe.java @@ -0,0 +1,81 @@ +/* + * 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.databinding.xml; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +public class SAX2DOMPipe extends BaseTransformer<ContentHandler, Node> implements DataPipeTransformer<ContentHandler, Node> { + + /** + * + */ + public SAX2DOMPipe() { + super(); + } + + /** + * @see org.apache.tuscany.sca.databinding.DataPipeTransformer#newInstance() + */ + public DataPipe<ContentHandler, Node> newInstance() { + return new Pipe(); + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + protected Class<ContentHandler> getSourceType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 30; + } + + private static class Pipe implements DataPipe<ContentHandler, Node> { + private SAX2DOM pipe; + + public Pipe() { + super(); + try { + this.pipe = new SAX2DOM(); + } catch (ParserConfigurationException e) { + throw new IllegalArgumentException(e); + } + } + + public Node getResult() { + return pipe.getDOM(); + } + + public ContentHandler getSink() { + return pipe; + } + + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleJavaType2Node.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleJavaType2Node.java new file mode 100644 index 0000000000..d2625fba11 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleJavaType2Node.java @@ -0,0 +1,71 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.apache.tuscany.sca.databinding.impl.Java2SimpleTypeTransformer; +import org.apache.tuscany.sca.databinding.javabeans.Java2XMLMapperException; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transformer to convert data from an simple OMElement to Java Object + * + * @version $Rev$ $Date$ + */ +public class SimpleJavaType2Node extends Java2SimpleTypeTransformer<Node> { + + private Document factory; + + public SimpleJavaType2Node() { + super(); + try { + factory = DOMHelper.newDocument(); + } catch (ParserConfigurationException e) { + throw new Java2XMLMapperException(e); + } + } + + @Override + protected Node createElement(QName element, String text, TransformationContext context) { + if (element == null) { + element = DOMDataBinding.ROOT_ELEMENT; + } + Node root = DOMHelper.createElement(factory, element); + if (text != null) { + root.appendChild(factory.createTextNode(text)); + } else { + Attr nil = factory.createAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:nil"); + nil.setValue("true"); + root.appendChild(nil); + } + return root; + } + + @Override + public Class getTargetType() { + return Node.class; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleXmlNodeImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleXmlNodeImpl.java new file mode 100644 index 0000000000..e041f85214 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleXmlNodeImpl.java @@ -0,0 +1,112 @@ +/* + * 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.databinding.xml; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * @version $Rev$ $Date$ + */ +public class SimpleXmlNodeImpl implements XmlNode { + private static final String XSI_PREFIX = "xsi"; + private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance"; + private static final QName XSI_NIL = new QName(XSI_NS, "nil", XSI_PREFIX); + private static final Map<String, String> NS_MAP = new HashMap<String, String>(); + static { + NS_MAP.put(XSI_PREFIX, XSI_NS); + } + + protected Type type; + protected QName name; + protected Object value; + + public SimpleXmlNodeImpl(QName name, Object value) { + this(name, value, name != null ? Type.ELEMENT : Type.CHARACTERS); + } + + public SimpleXmlNodeImpl(QName name, Object value, Type type) { + super(); + this.type = type; + this.name = name; + this.value = value; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#attributes() + */ + public List<XmlNode> attributes() { + if (type == Type.ELEMENT && value == null) { + // Nil element + XmlNode attr = new SimpleXmlNodeImpl(XSI_NIL, "true"); + return Arrays.asList(attr); + } + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#children() + */ + public Iterator<XmlNode> children() { + if (type == Type.ELEMENT && value != null) { + // Nil element + XmlNode node = new SimpleXmlNodeImpl(null, value); + return Arrays.asList(node).iterator(); + } + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getName() + */ + public QName getName() { + return name; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getValue() + */ + public String getValue() { + return value == null ? null : String.valueOf(value); + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#namespaces() + */ + public Map<String, String> namespaces() { + if (type == Type.ELEMENT && value == null) { + return NS_MAP; + } + return null; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2NodeTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2NodeTransformer.java new file mode 100644 index 0000000000..ee9aa1bb76 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2NodeTransformer.java @@ -0,0 +1,69 @@ +/* + * 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.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transform TrAX Source to Node + * + * @version $Rev$ $Date$ + */ +public class Source2NodeTransformer extends BaseTransformer<Source, Node> implements + PullTransformer<Source, Node> { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public Node transform(Source source, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + DOMResult result = new DOMResult(); + transformer.transform(source, result); + Document doc = (Document) result.getNode(); + return DOMHelper.adjustElementName(context, doc.getDocumentElement()); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Source> getSourceType() { + return Source.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2ResultTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2ResultTransformer.java new file mode 100644 index 0000000000..8a2b6b39aa --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2ResultTransformer.java @@ -0,0 +1,63 @@ +/* + * 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.databinding.xml; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * Transform TrAX Source to Result + * + * @version $Rev$ $Date$ + */ +public class Source2ResultTransformer extends BaseTransformer<Source, Result> implements + PushTransformer<Source, Result> { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public void transform(Source source, Result result, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + transformer.transform(source, result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Source> getSourceType() { + return Source.class; + } + + @Override + protected Class<Result> getTargetType() { + return Result.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2StringTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2StringTransformer.java new file mode 100644 index 0000000000..2ed548ad76 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2StringTransformer.java @@ -0,0 +1,68 @@ +/* + * 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.databinding.xml; + +import java.io.StringWriter; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * Transform TrAX Source to String + * + * @version $Rev$ $Date$ + */ +public class Source2StringTransformer extends BaseTransformer<Source, String> implements + PullTransformer<Source, String> { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public String transform(Source source, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + StringWriter sw = new StringWriter(); + StreamResult result = new StreamResult(sw); + transformer.transform(source, result); + return sw.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Source> getSourceType() { + return Source.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAX2SAXAdapter.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAX2SAXAdapter.java new file mode 100644 index 0000000000..6257681091 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAX2SAXAdapter.java @@ -0,0 +1,256 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Adapter that converts from StAX to SAX event streams. Currently the following + * SAX events are not generated: + * <ul> + * <li>ignorableWhitespace</li> + * <li>skippedEntity</li> + * <ul> + * Also the following StAX events are not mapped: + * <ul> + * <li>CDATA</li> + * <li>COMMENT</li> + * <li>DTD</li> + * <li>ENTITY_DECLARATION</li> + * <li>ENTITY_REFERENCE</li> + * <li>NOTATION_DECLARATION</li> + * <li>SPACE</li> + * </ul> + * StAX ATTRIBUTE events are ignored but the equivalent attributes (derived from + * the START_ELEMENT event) are supplied in the SAX startElement event's + * Attributes parameter. If the adaptor is configured to pass namespace prefixes + * then namespace information will also be included in the Attributes; StAX + * NAMESPACE events are ignored. <p/> Another issue is namespace processing. If + * the reader is positioned at a sub-node, we cannot capture all the in-scope + * namespace bindings. Therefore we cannot re-create a proper SAX event stream + * from a StAX parser. <p/> For example <p/> <a:root xmlns:a="foo" + * xmlns:b="bar"><b:sub>a:foo</b:sub></a:root> <p/> And if + * you are handed a parser at <b:sub>, then your SAX events should look + * like: <p/> <b:sub xmlns:a="foo" xmlns:b="bar">a:foo</b:sub> <p/> + * not: <p/> <b:sub>a:foo</b:sub> <p/> <p/> Proposal: we change the + * receiver of SAX events (SDOXMLResourceImpl) so that it uses NamespaceContext + * to resolve prefix (as opposed to record start/endPrefixMappings and use it + * for resolution.) + * + * @version $Rev$ $Date$ + */ +public class StAX2SAXAdapter { + private final boolean namespacePrefixes; + + /** + * Construct a new StAX to SAX adapter that will convert a StAX event stream + * into a SAX event stream. + * + * @param namespacePrefixes whether xmlns attributes should be included in + * startElement events; + */ + public StAX2SAXAdapter(boolean namespacePrefixes) { + this.namespacePrefixes = namespacePrefixes; + } + + /** + * Pull events from the StAX stream and dispatch to the SAX ContentHandler. + * The StAX stream would typically be located on a START_DOCUMENT or + * START_ELEMENT event and when this method returns it will be located on + * the associated END_DOCUMENT or END_ELEMENT event. Behaviour with other + * start events is undefined. + * + * @param reader StAX event source to read + * @param handler SAX ContentHandler for processing events + * @throws XMLStreamException if there was a problem reading the stream + * @throws SAXException passed through from the ContentHandler + */ + public void parse(XMLStreamReader reader, ContentHandler handler) throws XMLStreamException, SAXException { + handler.setDocumentLocator(new LocatorAdaptor(reader.getLocation())); + + // remembers the nest level of elements to know when we are done + int level = 0; + int event = reader.getEventType(); + while (true) { + switch (event) { + case XMLStreamConstants.START_DOCUMENT: + level++; + handler.startDocument(); + break; + case XMLStreamConstants.START_ELEMENT: + level++; + handleStartElement(reader, handler); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + handler.processingInstruction(reader.getPITarget(), reader.getPIData()); + break; + case XMLStreamConstants.CHARACTERS: + handler.characters(reader.getTextCharacters(), reader.getTextStart(), reader + .getTextLength()); + break; + case XMLStreamConstants.END_ELEMENT: + handleEndElement(reader, handler); + level--; + if (level == 0) { + return; + } + break; + case XMLStreamConstants.END_DOCUMENT: + handler.endDocument(); + return; + /* + * uncomment to handle all events rather than just mapped + * ones // StAX events that are not mapped to SAX case + * XMLStreamConstants.COMMENT: case + * XMLStreamConstants.SPACE: case + * XMLStreamConstants.ENTITY_REFERENCE: case + * XMLStreamConstants.DTD: case XMLStreamConstants.CDATA: + * case XMLStreamConstants.NOTATION_DECLARATION: case + * XMLStreamConstants.ENTITY_DECLARATION: break; // StAX + * events handled in START_ELEMENT case + * XMLStreamConstants.ATTRIBUTE: case + * XMLStreamConstants.NAMESPACE: break; default: throw new + * AssertionError("Unknown StAX event: " + event); + */ + } + event = reader.next(); + } + } + + private void handleStartElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // send startPrefixMapping events immediately before startElement event + int nsCount = reader.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.startPrefixMapping(prefix, reader.getNamespaceURI(i)); + } + + // fire startElement + QName qname = reader.getName(); + String prefix = qname.getPrefix(); + String rawname; + if (prefix == null || prefix.length() == 0) { + rawname = qname.getLocalPart(); + } else { + rawname = prefix + ':' + qname.getLocalPart(); + } + Attributes attrs = getAttributes(reader); + handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs); + } + + private static void handleEndElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // fire endElement + QName qname = reader.getName(); + handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString()); + + // send endPrefixMapping events immediately after endElement event + // we send them in the opposite order to that returned but this is not + // actually required by SAX + int nsCount = reader.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.endPrefixMapping(prefix); + } + } + + /** + * Get the attributes associated with the current START_ELEMENT event. + * + * @return the StAX attributes converted to org.xml.sax.Attributes + */ + private Attributes getAttributes(XMLStreamReader reader) { + assert reader.getEventType() == XMLStreamConstants.START_ELEMENT; + + AttributesImpl attrs = new AttributesImpl(); + + // add namespace declarations if required + if (namespacePrefixes) { + for (int i = 0; i < reader.getNamespaceCount(); i++) { + String prefix = reader.getNamespacePrefix(i); + String uri = reader.getNamespaceURI(i); + attrs.addAttribute(null, prefix, "xmlns:" + prefix, "CDATA", uri); + } + } + + // Regular attributes + for (int i = 0; i < reader.getAttributeCount(); i++) { + String uri = reader.getAttributeNamespace(i); + if (uri == null) { + uri = ""; + } + String localName = reader.getAttributeLocalName(i); + String prefix = reader.getAttributePrefix(i); + String qname; + if (prefix == null || prefix.length() == 0) { + qname = localName; + } else { + qname = prefix + ':' + localName; + } + String type = reader.getAttributeType(i); + String value = reader.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qname, type, value); + } + + return attrs; + } + + /** + * Adaptor for mapping Locator information. + */ + private static final class LocatorAdaptor implements Locator { + private final Location location; + + private LocatorAdaptor(Location location) { + this.location = location; + } + + public int getColumnNumber() { + return location == null ? 0 : location.getColumnNumber(); + } + + public int getLineNumber() { + return location == null ? 0 : location.getLineNumber(); + } + + public String getPublicId() { + return location == null ? "" : location.getPublicId(); + } + + public String getSystemId() { + return location == null ? "" : location.getSystemId(); + } + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXDataBinding.java new file mode 100644 index 0000000000..52a1d02631 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXDataBinding.java @@ -0,0 +1,54 @@ +/* + * 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.databinding.xml; + + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * A DataBinding for the StAX + * + * @version $Rev$ $Date$ + */ +public class StAXDataBinding extends BaseDataBinding { + public static final String NAME = XMLStreamReader.class.getName(); + public static final String[] ALIASES = new String[] {"stax"}; + + public StAXDataBinding() { + super(NAME, ALIASES, XMLStreamReader.class); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (super.introspect(type, operation)) { + type.setLogical(XMLType.UNKNOWN); + type.setDataBinding(NAME); + return true; + } else { + return false; + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXHelper.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXHelper.java new file mode 100644 index 0000000000..103ecbd7d1 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXHelper.java @@ -0,0 +1,86 @@ +/* + * 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.databinding.xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Source; + + +public final class StAXHelper { + private static final XMLInputFactory INPUT_FACTORY = XMLInputFactory.newInstance(); + private static final XMLOutputFactory OUTPUT_FACTORY = XMLOutputFactory.newInstance(); + + private StAXHelper() { + } + + public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(inputStream); + } + + public static XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(reader); + } + + public static XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(source); + } + + public static XMLStreamReader createXMLStreamReader(String string) throws XMLStreamException { + StringReader reader = new StringReader(string); + return createXMLStreamReader(reader); + } + + public static String save(XMLStreamReader reader) throws XMLStreamException { + StringWriter writer = new StringWriter(); + save(reader, writer); + return writer.toString(); + } + + public static void save(XMLStreamReader reader, OutputStream outputStream) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(outputStream); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, Writer writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(writer); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + serializer.serialize(reader, writer); + writer.flush(); + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StreamDataPipe.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StreamDataPipe.java new file mode 100644 index 0000000000..f8967e35b6 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StreamDataPipe.java @@ -0,0 +1,65 @@ +/* + * 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.databinding.xml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class StreamDataPipe extends BaseTransformer<OutputStream, InputStream> implements + DataPipeTransformer<OutputStream, InputStream> { + + public DataPipe<OutputStream, InputStream> newInstance() { + return new Pipe(); + } + + @Override + protected Class<InputStream> getTargetType() { + return InputStream.class; + } + + @Override + public int getWeight() { + return 50; + } + + @Override + protected Class<OutputStream> getSourceType() { + return OutputStream.class; + } + + public static class Pipe implements DataPipe<OutputStream, InputStream> { + private ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + public InputStream getResult() { + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + public OutputStream getSink() { + return outputStream; + } + + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2Node.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2Node.java new file mode 100644 index 0000000000..062e10cc45 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2Node.java @@ -0,0 +1,60 @@ +/* + * 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.databinding.xml; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +public class String2Node extends BaseTransformer<String, Node> implements PullTransformer<String, Node> { + + public Node transform(String source, TransformationContext context) { + try { + DocumentBuilder builder = DOMHelper.newDocumentBuilder(); + InputSource inputSource = new InputSource(new StringReader(source)); + return builder.parse(inputSource); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 50; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SAX.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SAX.java new file mode 100644 index 0000000000..c56dba1843 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SAX.java @@ -0,0 +1,61 @@ +/* + * 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.databinding.xml; + +import java.io.StringReader; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + * + * @version $Rev$ $Date$ + */ +public class String2SAX extends BaseTransformer<String, ContentHandler> implements + PushTransformer<String, ContentHandler> { + + public void transform(String source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(new StringReader(source)), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SourceTransformer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SourceTransformer.java new file mode 100644 index 0000000000..c2de202a9b --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SourceTransformer.java @@ -0,0 +1,62 @@ +/* + * 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.databinding.xml; + +import java.io.StringReader; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * Transform XML String to Source + * + * @version $Rev$ $Date$ + */ +public class String2SourceTransformer extends BaseTransformer<String, Source> implements + PullTransformer<String, Source> { + + public Source transform(String source, TransformationContext context) { + try { + return new StreamSource(new StringReader(source)); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<Source> getTargetType() { + return Source.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2XMLStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2XMLStreamReader.java new file mode 100644 index 0000000000..a7364006d0 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2XMLStreamReader.java @@ -0,0 +1,55 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class String2XMLStreamReader extends BaseTransformer<String, XMLStreamReader> implements + PullTransformer<String, XMLStreamReader> { + + public XMLStreamReader transform(String source, TransformationContext context) { + try { + return StAXHelper.createXMLStreamReader(source); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 50; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/WrappingXMLStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/WrappingXMLStreamReader.java new file mode 100644 index 0000000000..d73e495798 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/WrappingXMLStreamReader.java @@ -0,0 +1,100 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.StreamReaderDelegate; + +public class WrappingXMLStreamReader extends StreamReaderDelegate implements XMLFragmentStreamReader { + + private boolean done; + private int level; + + public WrappingXMLStreamReader(XMLStreamReader realReader) throws XMLStreamException { + super(realReader); + if (realReader == null) { + throw new UnsupportedOperationException("Reader cannot be null"); + } + + if (realReader instanceof XMLFragmentStreamReader) { + ((XMLFragmentStreamReader)realReader).init(); + } + + if (realReader.getEventType() == START_DOCUMENT) { + // Position to the 1st element + realReader.nextTag(); + } + if (realReader.getEventType() != START_ELEMENT) { + throw new IllegalStateException("The reader is not positioned at START_DOCUMENT or START_ELEMENT"); + } + this.done = false; + this.level = 1; + } + + @Override + public boolean hasNext() throws XMLStreamException { + return !done && super.hasNext(); + } + + @Override + public int next() throws XMLStreamException { + if (!hasNext()) { + throw new IllegalStateException("No more events"); + } + int event = super.next(); + if (!super.hasNext()) { + done = true; + } + if (event == START_ELEMENT) { + level++; + } else if (event == END_ELEMENT) { + level--; + if (level == 0) { + done = true; + } + } + return event; + } + + @Override + public int nextTag() throws XMLStreamException { + int event = 0; + while (true) { + event = next(); + if (event == START_ELEMENT || event == END_ELEMENT) { + return event; + } + } + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // nothing to do here + } + + public void init() { + // Nothing to do here + } + + public boolean isDone() { + return done; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Writer2ReaderDataPipe.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Writer2ReaderDataPipe.java new file mode 100644 index 0000000000..5ab7272d58 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Writer2ReaderDataPipe.java @@ -0,0 +1,63 @@ +/* + * 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.databinding.xml; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class Writer2ReaderDataPipe extends BaseTransformer<Writer, Reader> implements DataPipeTransformer<Writer, Reader> { + + public DataPipe<Writer, Reader> newInstance() { + return new Pipe(); + } + + @Override + protected Class<Reader> getTargetType() { + return Reader.class; + } + + @Override + public int getWeight() { + return 50; + } + + @Override + protected Class<Writer> getSourceType() { + return Writer.class; + } + + private static class Pipe implements DataPipe<Writer, Reader> { + private StringWriter writer = new StringWriter(); + + public Reader getResult() { + return new StringReader(writer.toString()); + } + + public Writer getSink() { + return writer; + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLDocumentStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLDocumentStreamReader.java new file mode 100644 index 0000000000..cd33e64176 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLDocumentStreamReader.java @@ -0,0 +1,482 @@ +/* + * 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.databinding.xml; + +import java.util.NoSuchElementException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * This class is derived from Apache Axis2 class + * org.apache.axis2.util.StreamWrapper</a>. It's used wrap a XMLStreamReader to + * create a XMLStreamReader representing a document and it will produce + * START_DOCUMENT, END_DOCUMENT events. + * + * @version $Rev$ $Date$ + */ +public class XMLDocumentStreamReader implements XMLStreamReader { + private static final int STATE_COMPLETE_AT_NEXT = 2; // The wrapper + // will produce + // END_DOCUMENT + + private static final int STATE_COMPLETED = 3; // Done + + private static final int STATE_INIT = 0; // The wrapper will produce + // START_DOCUMENT + + private static final int STATE_SWITCHED = 1; // The real reader will + // produce events + + private XMLStreamReader realReader; + private boolean fragment; + private int level = 0; + + private int state = STATE_INIT; + + public XMLDocumentStreamReader(XMLStreamReader realReader) { + if (realReader == null) { + throw new UnsupportedOperationException("Reader cannot be null"); + } + + this.realReader = realReader; + + if (realReader instanceof XMLFragmentStreamReader) { + ((XMLFragmentStreamReader)realReader).init(); + } + + // If the real reader is positioned at START_DOCUMENT, always use + // the real reader + if (realReader.getEventType() == START_DOCUMENT) { + fragment = false; + state = STATE_SWITCHED; + } + } + + public void close() throws XMLStreamException { + realReader.close(); + } + + public int getAttributeCount() { + if (isDelegating()) { + return realReader.getAttributeCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (isDelegating()) { + return realReader.getAttributeLocalName(i); + } else { + throw new IllegalStateException(); + } + } + + public QName getAttributeName(int i) { + if (isDelegating()) { + return realReader.getAttributeName(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (isDelegating()) { + return realReader.getAttributeNamespace(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (isDelegating()) { + return realReader.getAttributePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + if (isDelegating()) { + return realReader.getAttributeType(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(int i) { + if (isDelegating()) { + return realReader.getAttributeValue(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(String s, String s1) { + if (isDelegating()) { + return realReader.getAttributeValue(s, s1); + } else { + throw new IllegalStateException(); + } + } + + public String getCharacterEncodingScheme() { + return realReader.getCharacterEncodingScheme(); + } + + public String getElementText() throws XMLStreamException { + if (isDelegating()) { + return realReader.getElementText(); + } else { + throw new XMLStreamException(); + } + } + + public String getEncoding() { + return realReader.getEncoding(); + } + + public int getEventType() { + int event = -1; + switch (state) { + case STATE_SWITCHED: + case STATE_COMPLETE_AT_NEXT: + event = realReader.getEventType(); + break; + case STATE_INIT: + event = START_DOCUMENT; + break; + case STATE_COMPLETED: + event = END_DOCUMENT; + break; + } + return event; + } + + public String getLocalName() { + if (isDelegating()) { + return realReader.getLocalName(); + } else { + throw new IllegalStateException(); + } + } + + public Location getLocation() { + if (isDelegating()) { + return realReader.getLocation(); + } else { + return null; + } + } + + public QName getName() { + if (isDelegating()) { + return realReader.getName(); + } else { + throw new IllegalStateException(); + } + } + + public NamespaceContext getNamespaceContext() { + return realReader.getNamespaceContext(); + } + + public int getNamespaceCount() { + if (isDelegating()) { + return realReader.getNamespaceCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespacePrefix(int i) { + if (isDelegating()) { + return realReader.getNamespacePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI() { + if (isDelegating()) { + return realReader.getNamespaceURI(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(int i) { + if (isDelegating()) { + return realReader.getNamespaceURI(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(String s) { + if (isDelegating()) { + return realReader.getNamespaceURI(s); + } else { + throw new IllegalStateException(); + } + } + + public String getPIData() { + if (isDelegating()) { + return realReader.getPIData(); + } else { + throw new IllegalStateException(); + } + } + + public String getPITarget() { + if (isDelegating()) { + return realReader.getPITarget(); + } else { + throw new IllegalStateException(); + } + } + + public String getPrefix() { + if (isDelegating()) { + return realReader.getPrefix(); + } else { + throw new IllegalStateException(); + } + } + + public Object getProperty(String s) throws IllegalArgumentException { + if (isDelegating()) { + return realReader.getProperty(s); + } else { + throw new IllegalArgumentException(); + } + } + + public String getText() { + if (isDelegating()) { + return realReader.getText(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (isDelegating()) { + return realReader.getTextCharacters(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (isDelegating()) { + return realReader.getTextCharacters(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (isDelegating()) { + return realReader.getTextLength(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (isDelegating()) { + return realReader.getTextStart(); + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + if (isDelegating()) { + return realReader.getVersion(); + } else { + return null; + } + } + + public boolean hasName() { + if (isDelegating()) { + return realReader.hasName(); + } else { + return false; + } + } + + public boolean hasNext() throws XMLStreamException { + if (state == STATE_COMPLETE_AT_NEXT) { + return true; + } else if (state == STATE_COMPLETED) { + return false; + } else if (state == STATE_SWITCHED) { + return realReader.hasNext(); + } else { + return true; + } + } + + public boolean hasText() { + if (isDelegating()) { + return realReader.hasText(); + } else { + return false; + } + } + + public boolean isAttributeSpecified(int i) { + if (isDelegating()) { + return realReader.isAttributeSpecified(i); + } else { + return false; + } + } + + public boolean isCharacters() { + if (isDelegating()) { + return realReader.isCharacters(); + } else { + return false; + } + } + + private boolean isDelegating() { + return state == STATE_SWITCHED || state == STATE_COMPLETE_AT_NEXT; + } + + public boolean isEndElement() { + if (isDelegating()) { + return realReader.isEndElement(); + } else { + return false; + } + } + + public boolean isStandalone() { + if (isDelegating()) { + return realReader.isStandalone(); + } else { + return false; + } + } + + public boolean isStartElement() { + if (isDelegating()) { + return realReader.isStartElement(); + } else { + return false; + } + } + + public boolean isWhiteSpace() { + if (isDelegating()) { + return realReader.isWhiteSpace(); + } else { + return false; + } + } + + public int next() throws XMLStreamException { + int returnEvent; + + switch (state) { + case STATE_SWITCHED: + returnEvent = realReader.next(); + if (returnEvent == END_DOCUMENT) { + state = STATE_COMPLETED; + } else if (!realReader.hasNext()) { + state = STATE_COMPLETE_AT_NEXT; + } + if (fragment && returnEvent == END_ELEMENT) { + level--; + if (level == 0) { + // We are now at the end of the top-level element in the fragment + state = STATE_COMPLETE_AT_NEXT; + } + } + if (fragment && returnEvent == START_ELEMENT) { + level++; + } + break; + case STATE_INIT: + state = STATE_SWITCHED; + returnEvent = realReader.getEventType(); + if (returnEvent == START_ELEMENT) { + // The real reader is positioned at the top-level element in the fragment + level = 0; + fragment = true; + } + break; + case STATE_COMPLETE_AT_NEXT: + state = STATE_COMPLETED; + returnEvent = END_DOCUMENT; + break; + case STATE_COMPLETED: + // oops - no way we can go beyond this + throw new NoSuchElementException("End of stream has reached."); + default: + throw new UnsupportedOperationException(); + } + + return returnEvent; + } + + public int nextTag() throws XMLStreamException { + if (isDelegating()) { + int returnEvent = realReader.nextTag(); + if (fragment && returnEvent == END_ELEMENT) { + level--; + if (level == 0) { + // We are now at the end of the top-level element in the fragment + state = STATE_COMPLETE_AT_NEXT; + } + } + if (fragment && returnEvent == START_ELEMENT) { + level++; + } + return returnEvent; + } else { + throw new XMLStreamException(); + } + } + + public void require(int i, String s, String s1) throws XMLStreamException { + if (isDelegating()) { + realReader.require(i, s, s1); + } + } + + public boolean standaloneSet() { + if (isDelegating()) { + return realReader.standaloneSet(); + } else { + return false; + } + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReader.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReader.java new file mode 100644 index 0000000000..a42d6acc9a --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReader.java @@ -0,0 +1,53 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +public interface XMLFragmentStreamReader extends XMLStreamReader { + QName NIL_QNAME = new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi"); + String NIL_VALUE_TRUE = "true"; + + /** + * this will help to handle Text within the current element. user should + * pass the element text to the property list as this ELEMENT_TEXT as the + * key. This key deliberately has a space in it so that it is not a valid + * XML name + */ + String ELEMENT_TEXT = "Element Text"; + + /** + * Extra method to query the state of the pullparser + */ + boolean isDone(); + + /** + * add the parent namespace context to this parser + */ + void setParentNamespaceContext(NamespaceContext nsContext); + + /** + * Initiate the parser - this will do whatever the needed tasks to initiate + * the parser and must be called before attempting any specific parsing + * using this parser + */ + void init(); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReaderImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReaderImpl.java new file mode 100644 index 0000000000..f1084cf2a3 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReaderImpl.java @@ -0,0 +1,857 @@ +/* + * 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.databinding.xml; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * This is the new implementation of the XMLFramentStreamReader. The approach + * here is simple When the pull parser needs to generate events for a particular + * name-value(s) pair it always hands over (delegates) the task to another pull + * parser which knows how to deal with it The common types of name value pairs + * we'll come across are + * <ul> + * <li> String name/QName name - String value + * <li> String name/QName name - String[] value + * <li> QName name/String name - XMLStreamReader value + * <li> QName name/String name - XMLStreamable value + * <li> QName name/String name - Java bean + * <li> QName name/String name - Datahandler + * + * </ul> + * <p/> As for the attributes, these are the possible combinations in the array + * <ul> + * <li> String name/QName name - String value + * </ul> + * Note that certain array methods have been deliberately removed to avoid + * complications. The generated code will take the trouble to lay the elements + * of the array in the correct order <p/> <p/> Hence there will be a parser impl + * that knows how to handle these types, and this parent parser will always + * delegate these tasks to the child pullparasers in effect this is one huge + * state machine that has only a few states and delegates things down to the + * child parsers whenever possible <p/> + * + * @version $Rev$ $Date$ + */ +public class XMLFragmentStreamReaderImpl implements XMLFragmentStreamReader { + + private static final int DELEGATED_STATE = 2; + private static final int END_ELEMENT_STATE = 1; + // states for this pullparser - it can only have four states + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 3; + + protected NamedProperty[] attributes; + + // reference to the child reader + protected XMLFragmentStreamReader childReader; + // current property index + // initialized at zero + protected int index; + protected Map<String, String> declaredNamespaceMap = new HashMap<String, String>(); + protected QName elementQName; + + // we always create a new namespace context + protected DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + + protected NamedProperty[] elements; + + // integer field that keeps the state of this + // parser. + protected int state = START_ELEMENT_STATE; + + /* + * we need to pass in a namespace context since when delegated, we've no + * idea of the current namespace context. So it needs to be passed on here! + */ + public XMLFragmentStreamReaderImpl(QName elementQName, NamedProperty[] elements, NamedProperty[] attributes) { + // validate the lengths, since both the arrays are supposed + // to have + this.elements = elements == null ? new NamedProperty[0] : elements; + this.elementQName = elementQName; + this.attributes = attributes == null ? new NamedProperty[0] : attributes; + } + + protected XMLFragmentStreamReaderImpl(QName elementQName) { + this.elementQName = elementQName; + } + + /** + * add the namespace context + */ + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // register the namespace context passed in to this + this.namespaceContext.setParentNsContext(nsContext); + + } + + protected NamedProperty[] getElements() { + return elements; + } + + protected NamedProperty[] getAttributes() { + return attributes; + } + + protected QName[] getNamespaces() { + return new QName[0]; + } + + /** + * @param prefix + * @param uri + */ + protected void addToNsMap(String prefix, String uri) { + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + namespaceContext.pushNamespace(prefix, uri); + declaredNamespaceMap.put(prefix, uri); + } + } + + public void close() throws XMLStreamException { + // do nothing here - we have no resources to free + } + + public int getAttributeCount() { + return (state == DELEGATED_STATE) ? childReader.getAttributeCount() : (state == START_ELEMENT_STATE + ? getAttributes().length : 0); + } + + public String getAttributeLocalName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeLocalName(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getLocalPart(); + } + } else { + throw new IllegalStateException(); + } + } + + /** + * @param i + */ + public QName getAttributeName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeName(i); + } else if (state == START_ELEMENT_STATE) { + if ((i >= (getAttributes().length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + QName attribPointer = getAttributes()[i].getKey(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer == null) { + throw new UnsupportedOperationException(); + } else if (attribPointer instanceof QName) { + return attribPointer; + } else { + return null; + } + } + } else { + throw new IllegalStateException(); // as per the API contract + } + + } + + public String getAttributeNamespace(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeNamespace(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getNamespaceURI(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributePrefix(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getPrefix(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not supported + } + + public String getAttributeValue(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeValue(i); + } else if (state == START_ELEMENT_STATE) { + if ((i >= (getAttributes().length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + QName attribPointer = getAttributes()[i].getKey(); + Object omAttribObj = getAttributes()[i].getValue(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer == null) { + throw new UnsupportedOperationException(); + } else if (attribPointer instanceof QName) { + return (String)omAttribObj; + } else { + return null; + } + } + } else { + throw new IllegalStateException(); + } + + } + + public String getAttributeValue(String nsUri, String localName) { + + int attribCount = getAttributeCount(); + String returnValue = null; + QName attribQualifiedName; + for (int i = 0; i < attribCount; i++) { + attribQualifiedName = getAttributeName(i); + if (nsUri == null) { + if (localName.equals(attribQualifiedName.getLocalPart())) { + returnValue = getAttributeValue(i); + break; + } + } else { + if (localName.equals(attribQualifiedName.getLocalPart()) && nsUri.equals(attribQualifiedName + .getNamespaceURI())) { + returnValue = getAttributeValue(i); + break; + } + } + + } + + return returnValue; + } + + public String getCharacterEncodingScheme() { + return null; // TODO - should we return something for this ? + } + + /** + * TODO implement the right contract for this + * + * @throws XMLStreamException + */ + public String getElementText() throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getElementText(); + } else { + return null; + } + + } + + // ///////////////////////////////////////////////////////////////////////// + // / attribute handling + // ///////////////////////////////////////////////////////////////////////// + + public String getEncoding() { + if (state == DELEGATED_STATE) { + return childReader.getEncoding(); + } else { + // we've no idea what the encoding is going to be in this case + // perhaps we ought to return some constant here, which the user + // might + // have access to change! + return null; + } + } + + public int getEventType() { + if (state == START_ELEMENT_STATE) { + return START_ELEMENT; + } else if (state == END_ELEMENT_STATE) { + return END_ELEMENT; + } else if (state == TEXT_STATE) { + return CHARACTERS; + } else { // this is the delegated state + return childReader.getEventType(); + } + } + + public String getLocalName() { + if (state == DELEGATED_STATE) { + return childReader.getLocalName(); + } else if (state != TEXT_STATE) { + return elementQName.getLocalPart(); + } else { + throw new IllegalStateException(); + } + } + + /** + */ + public Location getLocation() { + // return a default location + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state == DELEGATED_STATE) { + return childReader.getName(); + } else if (state != TEXT_STATE) { + return elementQName; + } else { + throw new IllegalStateException(); + } + + } + + public NamespaceContext getNamespaceContext() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceContext(); + } else { + return namespaceContext; + } + + } + + public int getNamespaceCount() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceCount(); + } else { + return declaredNamespaceMap.size(); + } + } + + /** + * @param i + */ + public String getNamespacePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespacePrefix(i); + } else if (state != TEXT_STATE) { + // order the prefixes + String[] prefixes = makePrefixArray(); + if ((i >= prefixes.length) || (i < 0)) { + return null; + } else { + return prefixes[i]; + } + + } else { + throw new IllegalStateException(); + } + + } + + public String getNamespaceURI() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(); + } else if (state == TEXT_STATE) { + return null; + } else { + return elementQName.getNamespaceURI(); + } + } + + // ///////////////////////////////////////////////////////////////////////// + // //////////// end of attribute handling + // ///////////////////////////////////////////////////////////////////////// + + // ////////////////////////////////////////////////////////////////////////// + // //////////// namespace handling + // ////////////////////////////////////////////////////////////////////////// + + public String getNamespaceURI(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(i); + } else if (state != TEXT_STATE) { + String namespacePrefix = getNamespacePrefix(i); + return namespacePrefix == null ? null : (String)declaredNamespaceMap.get(namespacePrefix); + } else { + throw new IllegalStateException(); + } + + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public String getPIData() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPITarget() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPrefix() { + if (state == DELEGATED_STATE) { + return childReader.getPrefix(); + } else if (state == TEXT_STATE) { + return null; + } else { + String prefix = elementQName.getPrefix(); + return "".equals(prefix) ? null : prefix; + } + } + + // ///////////////////////////////////////////////////////////////////////// + // /////// end of namespace handling + // ///////////////////////////////////////////////////////////////////////// + + /** + * @param key + * @throws IllegalArgumentException + */ + public Object getProperty(String key) throws IllegalArgumentException { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return null; + } else if (state == TEXT_STATE) { + return null; + } else if (state == DELEGATED_STATE) { + return childReader.getProperty(key); + } else { + return null; + } + + } + + public String getText() { + if (state == DELEGATED_STATE) { + return childReader.getText(); + } else if (state == TEXT_STATE) { + return (String)getElements()[index - 1].getValue(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(); + } else if (state == TEXT_STATE) { + return getElements()[index - 1].getValue() == null ? new char[0] : ((String)getElements()[index - 1] + .getValue()).toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + private int copy(int sourceStart, char[] target, int targetStart, int length) { + char[] source = getTextCharacters(); + if (sourceStart > source.length) { + throw new IndexOutOfBoundsException("source start > source length"); + } + int sourceLen = source.length - sourceStart; + if (length > sourceLen) { + length = sourceLen; + } + System.arraycopy(source, sourceStart, target, targetStart, length); + return sourceLen; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(i, chars, i1, i2); + } else if (state == TEXT_STATE) { + return copy(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == DELEGATED_STATE) { + return childReader.getTextLength(); + } else if (state == TEXT_STATE) { + return getTextCharacters().length; + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (state == DELEGATED_STATE) { + return childReader.getTextStart(); + } else if (state == TEXT_STATE) { + return 0; // assume text always starts at 0 + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + return null; + } + + public boolean hasName() { + // since this parser always has a name, the hasName + // has to return true if we are still navigating this element + // if not we should ask the child reader for it. + if (state == DELEGATED_STATE) { + return childReader.hasName(); + } else { + return state != TEXT_STATE; + } + } + + /** + * @throws XMLStreamException + */ + public boolean hasNext() throws XMLStreamException { + if (state == DELEGATED_STATE) { + if (childReader.isDone()) { + // the child reader is done. We shouldn't be getting the + // hasNext result from the child pullparser then + return true; + } else { + return childReader.hasNext(); + } + } else { + return state == START_ELEMENT_STATE || state == TEXT_STATE; + + } + } + + /** + * check the validity of this implementation + */ + public boolean hasText() { + if (state == DELEGATED_STATE) { + return childReader.hasText(); + } else { + return state == TEXT_STATE; + } + + } + + /** + * we need to split out the calling to the populate namespaces separately + * since this needs to be done *after* setting the parent namespace context. + * We cannot assume it will happen at construction! + */ + public void init() { + // here we have an extra issue to attend to. we need to look at the + // prefixes and URIs (the combination) and populate a HashMap of + // namespaces. The HashMap of namespaces will be used to serve the + // namespace context + + populateNamespaceContext(); + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + public boolean isCharacters() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isCharacters(); + } + + /** + * are we done ? + */ + public boolean isDone() { + return state == END_ELEMENT_STATE; + } + + public boolean isEndElement() { + if (state == START_ELEMENT_STATE) { + return false; + } else if (state == END_ELEMENT_STATE) { + return true; + } + return childReader.isEndElement(); + } + + public boolean isStandalone() { + return true; + } + + public boolean isStartElement() { + if (state == START_ELEMENT_STATE) { + return true; + } else if (state == END_ELEMENT_STATE) { + return false; + } + return childReader.isStartElement(); + } + + public boolean isWhiteSpace() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isWhiteSpace(); + } + + /** + * Get the prefix list from the HashTable and take that into an array + */ + private String[] makePrefixArray() { + String[] prefixes = declaredNamespaceMap.keySet().toArray(new String[declaredNamespaceMap.size()]); + Arrays.sort(prefixes); + return prefixes; + } + + /** + * By far this should be the most important method in this class this method + * changes the state of the parser + */ + public int next() throws XMLStreamException { + int returnEvent = -1; // invalid state is the default state + switch (state) { + case START_ELEMENT_STATE: + // current element is start element. We should be looking at the + // property list and making a pullparser for the property value + if (getElements() == null || getElements().length == 0) { + // no properties - move to the end element state + // straight away + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + // there are properties. now we should delegate this task to + // a + // child reader depending on the property type + returnEvent = processProperties(); + + } + break; + case END_ELEMENT_STATE: + // we've reached the end element already. If the user tries to + // push + // further ahead then it is an exception + throw new XMLStreamException("Trying to go beyond the end of the pullparser"); + + case DELEGATED_STATE: + if (childReader.isDone()) { + // we've reached the end! + if (index > (getElements().length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + } else { + returnEvent = childReader.next(); + } + break; + + case TEXT_STATE: + // if there are any more event we should be delegating to + // processProperties. if not we just return an end element + if (index > (getElements().length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + break; + } + return returnEvent; + } + + // ///////////////////////////////////////////////////////////////////////// + // / Other utility methods + // //////////////////////////////////////////////////////////////////////// + + /** + * TODO implement this + * + * @throws XMLStreamException + */ + public int nextTag() throws XMLStreamException { + return 0; + } + + /** + * Populates a namespace context + */ + private void populateNamespaceContext() { + + // first add the current element namespace to the namespace context + // declare it if not found + addToNsMap(elementQName.getPrefix(), elementQName.getNamespaceURI()); + + for (QName n : getNamespaces()) { + addToNsMap(n.getPrefix(), n.getNamespaceURI()); + } + + // traverse through the attributes and populate the namespace context + // the attrib list can be of many combinations + // the valid combinations are + // String - String + // QName - QName + // null - OMAttribute + + for (int i = 0; i < getAttributes().length; i++) { // jump in two + QName attrQName = getAttributes()[i].getKey(); + if (!"".equals(attrQName.getNamespaceURI())) { + addToNsMap(attrQName.getPrefix(), attrQName.getNamespaceURI()); + } + } + } + + /** + * A convenient method to reuse the properties + * + * @return event to be thrown + * @throws XMLStreamException + */ + private int processProperties() throws XMLStreamException { + // move to the next property depending on the current property + // index + QName propertyQName = getElements()[index].getKey(); + boolean textFound = false; + if (propertyQName == null) { + throw new XMLStreamException("property key cannot be null!"); + } else if (ELEMENT_TEXT.equals(propertyQName.getLocalPart())) { + // propPointer being a String has a special case + // that is it can be a the special constant ELEMENT_TEXT that + // says this text event + textFound = true; + } + + // OK! we got the key. Now look at the value + Object propertyValue = getElements()[index].getValue(); + // cater for the special case now + if (textFound) { + // no delegation here - make the parser null and immediately + // return with the event characters + childReader = null; + state = TEXT_STATE; + ++index; + return CHARACTERS; + } else if (propertyValue == null) { + // if the value is null we delegate the work to a nullable + // parser + childReader = new NilElementStreamReader(propertyQName); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else if (propertyValue instanceof String) { + // strings are handled by the NameValuePairStreamReader + childReader = new NameValuePairStreamReader(propertyQName, (String)propertyValue); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else if (propertyValue instanceof String[]) { + // string[] are handled by the NameValueArrayStreamReader + // if the array is empty - skip it + if (((String[])propertyValue).length == 0) { + // advance the index + ++index; + return processProperties(); + } else { + childReader = new NameValueArrayStreamReader(propertyQName, (String[])propertyValue); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } + + } else if (propertyValue instanceof XMLStreamable) { + // ADBbean has it's own method to get a reader + XMLStreamReader reader = ((XMLStreamable)propertyValue).getXMLStreamReader(propertyQName); + // we know for sure that this is an ADB XMLStreamreader. + // However we need to make sure that it is compatible + if (reader instanceof XMLFragmentStreamReader) { + childReader = (XMLFragmentStreamReader)reader; + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else { + // wrap it to make compatible + childReader = new WrappingXMLStreamReader(reader); + } + } else if (propertyValue instanceof XMLStreamReader) { + XMLStreamReader reader = (XMLStreamReader)propertyValue; + if (reader instanceof XMLFragmentStreamReader) { + childReader = (XMLFragmentStreamReader)reader; + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else { + // wrap it to make compatible + childReader = new WrappingXMLStreamReader(reader); + } + + } else { + // all special possibilities has been tried! Let's treat + // the thing as a bean and try generating events from it + childReader = new WrappingXMLStreamReader(new BeanXMLStreamReaderImpl(propertyQName, propertyValue)); + // we cannot register the namespace context here + } + + // set the state here + state = DELEGATED_STATE; + // we are done with the delegation + // increment the property index + ++index; + return childReader.getEventType(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + public boolean standaloneSet() { + return true; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLGroupDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLGroupDataBinding.java new file mode 100644 index 0000000000..f7c895db1e --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLGroupDataBinding.java @@ -0,0 +1,57 @@ +/* + * 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.databinding.xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.databinding.impl.GroupDataBinding; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * A Group DataBinding + * + * @version $Rev$ $Date$ + */ +public class XMLGroupDataBinding extends GroupDataBinding { + + public XMLGroupDataBinding() { + super(new Class[] {InputStream.class, OutputStream.class, Reader.class, Writer.class, + // Source.class, Result.class, + InputSource.class, ContentHandler.class, XMLStreamReader.class, + XMLStreamWriter.class, XMLEventReader.class, XMLEventWriter.class}); + } + + @Override + protected Object getLogical(Class<?> markerType, Operation operation) { + return XMLType.UNKNOWN; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2Node.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2Node.java new file mode 100644 index 0000000000..e2d0416aec --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2Node.java @@ -0,0 +1,75 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +/** + * Transform DOM Node to XML XMLStreamReader + * + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2Node extends BaseTransformer<XMLStreamReader, Node> implements + PullTransformer<XMLStreamReader, Node> { + + private XMLStreamReader2SAX stax2sax = new XMLStreamReader2SAX(); + + public Node transform(XMLStreamReader source, TransformationContext context) { + try { + DataPipe<ContentHandler, Node> pipe = new SAX2DOMPipe().newInstance(); + stax2sax.transform(source, pipe.getSink(), context); + Node node = pipe.getResult(); + source.close(); + if (node instanceof Document) { + Document doc = (Document)node; + return DOMHelper.adjustElementName(context, doc.getDocumentElement()); + } else { + return node; + } + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2SAX.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2SAX.java new file mode 100644 index 0000000000..9b39f039b1 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2SAX.java @@ -0,0 +1,70 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; + +/** + * XMLStreamReader to SAX events + * + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2SAX extends BaseTransformer<XMLStreamReader, ContentHandler> implements + PushTransformer<XMLStreamReader, ContentHandler> { + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#getWeight() + */ + @Override + public int getWeight() { + return 20; + } + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, + * java.lang.Object, + * org.apache.tuscany.sca.databinding.TransformationContext) + */ + public void transform(XMLStreamReader source, ContentHandler sink, TransformationContext context) { + StAX2SAXAdapter adapter = new StAX2SAXAdapter(false); + try { + adapter.parse(source, sink); + source.close(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2String.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2String.java new file mode 100644 index 0000000000..6db731bc9f --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2String.java @@ -0,0 +1,57 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class XMLStreamReader2String extends BaseTransformer<XMLStreamReader, String> implements + PullTransformer<XMLStreamReader, String> { + + public String transform(XMLStreamReader source, TransformationContext context) { + try { + String str = StAXHelper.save(source); + source.close(); + return str; + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamSerializer.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamSerializer.java new file mode 100644 index 0000000000..920ebb511c --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamSerializer.java @@ -0,0 +1,287 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +/** + * The XMLStreamSerializer pulls events from the XMLStreamReader and dumps into the XMLStreamWriter + * + * @version $Rev$ $Date$ + */ +public class XMLStreamSerializer implements XMLStreamConstants { + public static final String NAMESPACE_PREFIX = "ns"; + private static int namespaceSuffix; + + /* + * The behavior of the Serializer is such that it returns when it encounters the starting element for the second + * time. The depth variable tracks the depth of the Serializer and tells it when to return. Note that it is assumed + * that this Serialization starts on an Element. + */ + + /** + * Field depth + */ + private int depth; + + /** + * Generates a unique namespace prefix that is not in the scope of the NamespaceContext + * + * @param nsCtxt + * @return string + */ + private String generateUniquePrefix(NamespaceContext nsCtxt) { + String prefix = NAMESPACE_PREFIX + namespaceSuffix++; + // null should be returned if the prefix is not bound! + while (nsCtxt.getNamespaceURI(prefix) != null) { + prefix = NAMESPACE_PREFIX + namespaceSuffix++; + } + + return prefix; + } + + /** + * Method serialize. + * + * @param node + * @param writer + * @throws XMLStreamException + */ + public void serialize(XMLStreamReader node, XMLStreamWriter writer) throws XMLStreamException { + serializeNode(node, writer); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeAttributes(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + int count = reader.getAttributeCount(); + String prefix; + String namespaceName; + String writerPrefix; + for (int i = 0; i < count; i++) { + prefix = reader.getAttributePrefix(i); + namespaceName = reader.getAttributeNamespace(i); + /* + * Due to parser implementations returning null as the namespace URI (for the empty namespace) we need to + * make sure that we deal with a namespace name that is not null. The best way to work around this issue is + * to set the namespace URI to "" if it is null + */ + if (namespaceName == null) { + namespaceName = ""; + } + + writerPrefix = writer.getPrefix(namespaceName); + + if (!"".equals(namespaceName)) { + // prefix has already being declared but this particular + // attrib has a + // no prefix attached. So use the prefix provided by the + // writer + if (writerPrefix != null && (prefix == null || prefix.equals(""))) { + writer.writeAttribute(writerPrefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // writer prefix is available but different from the + // current + // prefix of the attrib. We should be declaring the new + // prefix + // as a namespace declaration + } else if (prefix != null && !"".equals(prefix) && !prefix.equals(writerPrefix)) { + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // prefix is null (or empty), but the namespace name is + // valid! it has not + // being written previously also. So we need to generate + // a prefix + // here + } else if (prefix == null || prefix.equals("")) { + prefix = generateUniquePrefix(writer.getNamespaceContext()); + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } else { + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } + } else { + // empty namespace is equal to no namespace! + writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i)); + } + + } + } + + /** + * Method serializeCData. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeCData(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCData(reader.getText()); + } + + /** + * Method serializeComment. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeComment(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeComment(reader.getText()); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeElement(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + String prefix = reader.getPrefix(); + String nameSpaceName = reader.getNamespaceURI(); + if (nameSpaceName != null) { + String writerPrefix = writer.getPrefix(nameSpaceName); + if (writerPrefix != null) { + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + } else { + if (prefix != null) { + writer.writeStartElement(prefix, reader.getLocalName(), nameSpaceName); + writer.writeNamespace(prefix, nameSpaceName); + // writer.setPrefix(prefix, nameSpaceName); + } else { + // [rfeng] We need to set default NS 1st before calling writeStateElement + writer.setDefaultNamespace(nameSpaceName); + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + writer.writeDefaultNamespace(nameSpaceName); + } + } + } else { + writer.writeStartElement(reader.getLocalName()); + } + + // add the namespaces + int count = reader.getNamespaceCount(); + String namespacePrefix; + for (int i = 0; i < count; i++) { + namespacePrefix = reader.getNamespacePrefix(i); + // [rfeng] The following is commented out to allow to default ns + // if (namespacePrefix != null && namespacePrefix.length() == 0) { + // continue; + // } + + serializeNamespace(namespacePrefix, reader.getNamespaceURI(i), writer); + } + + // add attributes + serializeAttributes(reader, writer); + + } + + /** + * Method serializeEndElement. + * + * @param writer + * @throws XMLStreamException + */ + protected void serializeEndElement(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndElement(); + } + + /** + * Method serializeNamespace. + * + * @param prefix + * @param uri + * @param writer + * @throws XMLStreamException + */ + private void serializeNamespace(String prefix, String uri, XMLStreamWriter writer) throws XMLStreamException { + String prefix1 = writer.getPrefix(uri); + if (prefix1 == null) { + writer.writeNamespace(prefix, uri); + // writer.setPrefix(prefix, uri); + } + } + + /** + * Method serializeNode. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + while (true) { + int event = reader.getEventType(); + if (event == START_ELEMENT) { + serializeElement(reader, writer); + depth++; + } else if (event == ATTRIBUTE) { + serializeAttributes(reader, writer); + } else if (event == CHARACTERS) { + serializeText(reader, writer); + } else if (event == COMMENT) { + serializeComment(reader, writer); + } else if (event == CDATA) { + serializeCData(reader, writer); + } else if (event == END_ELEMENT) { + serializeEndElement(writer); + depth--; + } else if (event == START_DOCUMENT) { + depth++; // if a start document is found then increment + writer.writeStartDocument(); + // the depth + } else if (event == END_DOCUMENT) { + if (depth != 0) { + depth--; // for the end document - reduce the depth + } + writer.writeEndDocument(); + } + if (depth == 0) { + break; + } + if (reader.hasNext()) { + reader.next(); + } else { + break; + } + } + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCharacters(reader.getText()); + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamable.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamable.java new file mode 100644 index 0000000000..f32f93d098 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamable.java @@ -0,0 +1,37 @@ +/* + * 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.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +/** + * An interface represents data that can be read using StAX streaming + * + * @version $Rev$ $Date$ + */ +public interface XMLStreamable { + /** + * Get the XMLStreamReader for StAX processing + * + * @param rootElementName the name of the element to be generated + * @return Returns a pull parser. + */ + XMLStreamReader getXMLStreamReader(QName rootElementName); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStringDataBinding.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStringDataBinding.java new file mode 100644 index 0000000000..36cf5e9c9b --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStringDataBinding.java @@ -0,0 +1,51 @@ +/* + * 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.databinding.xml; + + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * A DataBinding for the XML string + * + * @version $Rev$ $Date$ + */ +public class XMLStringDataBinding extends BaseDataBinding { + public static final String NAME = String.class.getName(); + public static final String[] ALIASES = new String[] {"xml.string"}; + + public XMLStringDataBinding() { + super(NAME, ALIASES, String.class); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (type.getPhysical() == String.class && NAME.equals(type.getDataBinding()) || ALIASES[0].equals(type.getDataBinding())) { + type.setDataBinding(NAME); + type.setLogical(XMLType.UNKNOWN); + return true; + } else { + return false; + } + } +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNode.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNode.java new file mode 100644 index 0000000000..86ebd627f7 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNode.java @@ -0,0 +1,69 @@ +/* + * 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.databinding.xml; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * @version $Rev$ $Date$ + */ +public interface XmlNode { + enum Type {ELEMENT, ATTRIBUTE, CHARACTERS, READER}; + /** + * Returns the children of the receiver as an <code>Iterator</code>. + */ + Iterator<XmlNode> children(); + + /** + * Returns the attributes of the element as an <code>List</code>. Namespace declarations + * should be excluded. + * + * @return + */ + List<XmlNode> attributes(); + + /** + * Returns a map of prefix to namespace URI + * @return + */ + Map<String, String> namespaces(); + + /** + * Return the QName of the element. If it's for a text node, the name is null. + * @return + */ + QName getName(); + + /** + * Return the text value of the leaf element + * @return + */ + <T> T getValue(); + + /** + * Return the type of the XML node + * @return + */ + Type getType(); +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNodeIterator.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNodeIterator.java new file mode 100644 index 0000000000..3dd125463e --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNodeIterator.java @@ -0,0 +1,355 @@ +/* + * 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.databinding.xml; + +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; + +/** + * @version $Rev$ $Date$ + */ +public class XmlNodeIterator implements Iterator<XmlNode> { + public static final int START = 0; + public static final int END = 1; + + protected FastStack<ElementHolder> stack; + protected int state; + protected NamespaceContextImpl nsContext; + + public XmlNodeIterator(XmlNode rootNode) { + super(); + List<XmlNode> v = new ArrayList<XmlNode>(1); + v.add(rootNode); + stack = new FastStack<ElementHolder>(); + Iterator<XmlNode> i = v.iterator(); + stack.push(new ElementHolder(null, i)); + this.state = START; + this.nsContext = new NamespaceContextImpl(null); + } + + public boolean hasNext() { + return !(stack.empty() || (state == END && stack.peek().parent == null)); + } + + public XmlNode next() { + this.state = START; + ElementHolder element = stack.peek(); + Iterator<XmlNode> it = element.children; + if (it == null || (!it.hasNext())) { + // End of the children, return END event of parent + stack.pop(); + this.state = END; + this.nsContext = (NamespaceContextImpl)nsContext.getParent(); + return element.parent; + } + XmlNode node = it.next(); + stack.push(new ElementHolder(node, node.children())); + this.nsContext = new NamespaceContextImpl(this.nsContext); + populateNamespaces(node); + return node; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public int getState() { + return state; + } + + public NamespaceContext getNamespaceContext() { + return nsContext; + } + + private void populateNamespaces(XmlNode element) { + if (element.getName() != null) { + if (element.namespaces() != null) { + for (Map.Entry<String, String> e : element.namespaces().entrySet()) { + nsContext.register(e.getKey(), e.getValue()); + } + } + } + } + + private static class ElementHolder { + private XmlNode parent; + private Iterator<XmlNode> children; + + public ElementHolder(XmlNode parent, Iterator<XmlNode> children) { + this.parent = parent; + this.children = children; + } + } + + private static class NamespaceContextImpl implements NamespaceContext { + private NamespaceContext parent; + private Map<String, String> map = new HashMap<String, String>(); + + /** + * @param parent + */ + public NamespaceContextImpl(NamespaceContext parent) { + super(); + this.parent = parent; + if (parent == null) { + map.put("xml", "http://www.w3.org/XML/1998/namespace"); + map.put("xmlns", "http://www.w3.org/2000/xmlns/"); + } + } + + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("Prefix is null"); + } + + String ns = (String)map.get(prefix); + if (ns != null) { + return ns; + } + if (parent != null) { + return parent.getNamespaceURI(prefix); + } + return null; + } + + public String getPrefix(String nsURI) { + if (nsURI == null) + throw new IllegalArgumentException("Namespace is null"); + for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext();) { + Map.Entry<String, String> entry = i.next(); + if (entry.getValue().equals(nsURI)) { + return entry.getKey(); + } + } + if (parent != null) { + return parent.getPrefix(nsURI); + } + return null; + } + + public Iterator getPrefixes(String nsURI) { + List<String> prefixList = new ArrayList<String>(); + for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext();) { + Map.Entry<String, String> entry = i.next(); + if (entry.getValue().equals(nsURI)) { + prefixList.add(entry.getKey()); + } + } + final Iterator currentIterator = prefixList.iterator(); + final Iterator parentIterator = parent != null ? null : parent.getPrefixes(nsURI); + return new Iterator() { + + public boolean hasNext() { + return currentIterator.hasNext() || (parentIterator != null && parentIterator.hasNext()); + } + + public Object next() { + if (!hasNext()) { + throw new IllegalStateException("End of iterator has reached"); + } + return currentIterator.hasNext() ? currentIterator.next() : parentIterator.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + + } + + public void register(String prefix, String ns) { + map.put(prefix, ns); + } + + public NamespaceContext getParent() { + return parent; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(map.toString()); + if (parent != null) { + sb.append("\nParent: "); + sb.append(parent); + } + return sb.toString(); + } + } + + /** + * An implementation of the {@link java.util.Stack} API that is based on an <code>ArrayList</code> instead of a + * <code>Vector</code>, so it is not synchronized to protect against multi-threaded access. The implementation is + * therefore operates faster in environments where you do not need to worry about multiple thread contention. + * <p> + * The removal order of an <code>ArrayStack</code> is based on insertion order: The most recently added element is + * removed first. The iteration order is <i>not</i> the same as the removal order. The iterator returns elements + * from the bottom up, whereas the {@link #remove()} method removes them from the top down. + * <p> + * Unlike <code>Stack</code>, <code>ArrayStack</code> accepts null entries. + */ + public static class FastStack<T> extends ArrayList<T> { + + /** Ensure Serialization compatibility */ + private static final long serialVersionUID = 2130079159931574599L; + + /** + * Constructs a new empty <code>ArrayStack</code>. The initial size is controlled by <code>ArrayList</code> + * and is currently 10. + */ + public FastStack() { + super(); + } + + /** + * Constructs a new empty <code>ArrayStack</code> with an initial size. + * + * @param initialSize the initial size to use + * @throws IllegalArgumentException if the specified initial size is negative + */ + public FastStack(int initialSize) { + super(initialSize); + } + + /** + * Return <code>true</code> if this stack is currently empty. + * <p> + * This method exists for compatibility with <code>java.util.Stack</code>. New users of this class should use + * <code>isEmpty</code> instead. + * + * @return true if the stack is currently empty + */ + public boolean empty() { + return isEmpty(); + } + + /** + * Returns the top item off of this stack without removing it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T peek() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return get(n - 1); + } + } + + /** + * Returns the n'th item down (zero-relative) from the top of this stack without removing it. + * + * @param n the number of items down to go + * @return the n'th item on the stack, zero relative + * @throws EmptyStackException if there are not enough items on the stack to satisfy this request + */ + public T peek(int n) throws EmptyStackException { + int m = (size() - n) - 1; + if (m < 0) { + throw new EmptyStackException(); + } else { + return get(m); + } + } + + /** + * Pops the top item off of this stack and return it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T pop() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return remove(n - 1); + } + } + + /** + * Pushes a new item onto the top of this stack. The pushed item is also returned. This is equivalent to calling + * <code>add</code>. + * + * @param item the item to be added + * @return the item just pushed + */ + public Object push(T item) { + add(item); + return item; + } + + /** + * Returns the top-most index for the object in the stack + * + * @param object the object to be searched for + * @return top-most index, or -1 if not found + */ + public int search(T object) { + int i = size() - 1; // Current index + while (i >= 0) { + T current = get(i); + if ((object == null && current == null) || (object != null && object.equals(current))) { + return i; + } + i--; + } + return -1; + } + + /** + * Returns the element on the top of the stack. + * + * @return the element on the top of the stack + * @throws EmptyStackException if the stack is empty + */ + public T get() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return get(size - 1); + } + + /** + * Removes the element on the top of the stack. + * + * @return the removed element + * @throws EmptyStackException if the stack is empty + */ + public T remove() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return remove(size - 1); + } + + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderImpl.java b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderImpl.java new file mode 100644 index 0000000000..f4bc357c7d --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderImpl.java @@ -0,0 +1,531 @@ +/* + * 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.databinding.xml; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * + * @version $Rev$ $Date$ + */ +public class XmlTreeStreamReaderImpl implements XMLStreamReader { + + protected int state; + protected XmlNodeIterator iterator; + protected XmlNode current; + + protected XMLStreamReader reader; + + /* + * we need to pass in a namespace context since when delegated, we've no + * idea of the current namespace context. So it needs to be passed on here! + */ + public XmlTreeStreamReaderImpl(XmlNode root) { + this.iterator = new XmlNodeIterator(root); + this.current = null; + this.state = START_DOCUMENT; + this.reader = null; + } + + public void close() throws XMLStreamException { + if (reader != null) { + reader.close(); + } + } + + private void checkElementState() { + if (getEventType() != START_ELEMENT && getEventType() != END_ELEMENT) { + throw new IllegalStateException(); + } + } + + private List<XmlNode> getAttributes() { + if (current != null && current.attributes() != null) { + return current.attributes(); + } else { + return Collections.emptyList(); + } + } + + public int getAttributeCount() { + checkElementState(); + if (reader != null) { + return reader.getAttributeCount(); + } + return getAttributes().size(); + } + + public String getAttributeLocalName(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeLocalName(i); + } + return getAttributes().get(i).getName().getLocalPart(); + } + + /** + * @param i + */ + public QName getAttributeName(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeName(i); + } + return getAttributes().get(i).getName(); + } + + public String getAttributeNamespace(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeNamespace(i); + } + return getAttributes().get(i).getName().getNamespaceURI(); + } + + public String getAttributePrefix(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributePrefix(i); + } + return getAttributes().get(i).getName().getPrefix(); + } + + public String getAttributeType(int i) { + if (reader != null) { + return reader.getAttributeType(i); + } + return null; // not supported + } + + public String getAttributeValue(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeValue(i); + } + return getAttributes().get(i).getValue(); + } + + public String getAttributeValue(String nsUri, String localName) { + checkElementState(); + if (reader != null) { + return reader.getAttributeValue(nsUri, localName); + } + int count = getAttributeCount(); + String value = null; + QName attrQName; + for (int i = 0; i < count; i++) { + attrQName = getAttributeName(i); + if (nsUri == null) { + if (localName.equals(attrQName.getLocalPart())) { + value = getAttributeValue(i); + break; + } + } else { + if (localName.equals(attrQName.getLocalPart()) && nsUri.equals(attrQName.getNamespaceURI())) { + value = getAttributeValue(i); + break; + } + } + + } + + return value; + } + + public String getCharacterEncodingScheme() { + if (reader != null) { + return reader.getCharacterEncodingScheme(); + } + return "UTF-8"; + } + + public String getElementText() throws XMLStreamException { + checkElementState(); + if (reader != null) { + return reader.getElementText(); + } + return current.getValue(); + } + + public String getEncoding() { + if (reader != null) { + return reader.getEncoding(); + } + return "UTF-8"; + } + + public int getEventType() { + return state; + } + + public String getLocalName() { + checkElementState(); + if (reader != null) { + return reader.getLocalName(); + } + return current.getName().getLocalPart(); + } + + /** + */ + public Location getLocation() { + if (reader != null) { + return reader.getLocation(); + } + // return a default location + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + checkElementState(); + if (reader != null) { + return reader.getName(); + } + return current.getName(); + } + + public NamespaceContext getNamespaceContext() { + if (reader != null) { + return reader.getNamespaceContext(); + } + return iterator.getNamespaceContext(); + } + + private Map<String, String> getNamespaces() { + if (current != null && current.namespaces() != null) { + return current.namespaces(); + } else { + return Collections.emptyMap(); + } + } + + public int getNamespaceCount() { + checkElementState(); + if (reader != null) { + return reader.getNamespaceCount(); + } + return getNamespaces().size(); + } + + /** + * @param i + */ + public String getNamespacePrefix(int i) { + checkElementState(); + if (reader != null) { + return reader.getNamespacePrefix(i); + } + return new ArrayList<Map.Entry<String, String>>(getNamespaces().entrySet()).get(i).getKey(); + } + + public String getNamespaceURI() { + checkElementState(); + if (reader != null) { + return reader.getNamespaceURI(); + } + return current.getName().getNamespaceURI(); + } + + public String getNamespaceURI(int i) { + checkElementState(); + if (reader != null) { + return reader.getNamespaceURI(i); + } + return new ArrayList<Map.Entry<String, String>>(getNamespaces().entrySet()).get(i).getValue(); + } + + public String getNamespaceURI(String prefix) { + if (reader != null) { + return reader.getNamespaceURI(prefix); + } + return getNamespaceContext().getNamespaceURI(prefix); + } + + public String getPIData() { + if (reader != null) { + return reader.getPIData(); + } + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPITarget() { + if (reader != null) { + return reader.getPITarget(); + } + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPrefix() { + if (reader != null) { + return reader.getPrefix(); + } + if (state == START_ELEMENT || state == END_ELEMENT) { + String prefix = current.getName().getPrefix(); + return "".equals(prefix) ? null : prefix; + } else if (state == START_DOCUMENT) { + return null; + } else { + throw new IllegalStateException("State==" + state); + } + } + + /** + * @param key + * @throws IllegalArgumentException + */ + public Object getProperty(String key) throws IllegalArgumentException { + if (reader != null) { + return reader.getProperty(key); + } + return null; + } + + public String getText() { + if (reader != null) { + return reader.getText(); + } + return current.getValue(); + } + + public char[] getTextCharacters() { + if (reader != null) { + return reader.getTextCharacters(); + } + String value = current.getValue(); + return value == null ? new char[0] : value.toCharArray(); + } + + private int copy(int sourceStart, char[] target, int targetStart, int length) { + char[] source = getTextCharacters(); + if (sourceStart > source.length) { + throw new IndexOutOfBoundsException("source start > source length"); + } + int sourceLen = source.length - sourceStart; + if (length > sourceLen) { + length = sourceLen; + } + System.arraycopy(source, sourceStart, target, targetStart, length); + return sourceLen; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (reader != null) { + return reader.getTextCharacters(i, chars, i1, i2); + } + return copy(i, chars, i1, i2); + } + + public int getTextLength() { + if (reader != null) { + return reader.getTextLength(); + } + return getTextCharacters().length; + } + + public int getTextStart() { + if (reader != null) { + return reader.getTextStart(); + } + return 0; + } + + public String getVersion() { + return "1.0"; + } + + public boolean hasName() { + if (reader != null) { + return reader.hasName(); + } + return current.getName() != null; + } + + /** + * @throws XMLStreamException + */ + public boolean hasNext() throws XMLStreamException { + return iterator.hasNext() || state != END_DOCUMENT || (reader != null && reader.hasNext()); + } + + public boolean hasText() { + if (reader != null) { + return reader.hasText(); + } + return current.getType() == XmlNode.Type.CHARACTERS; + } + + public boolean isAttributeSpecified(int i) { + if (reader != null) { + return reader.isAttributeSpecified(i); + } + return false; // not supported + } + + public boolean isCharacters() { + if (reader != null) { + return reader.isCharacters(); + } + return current.getType() == XmlNode.Type.CHARACTERS; + } + + public boolean isEndElement() { + if (reader != null) { + return reader.isEndElement(); + } + return getEventType() == END_ELEMENT; + } + + public boolean isStandalone() { + return true; + } + + public boolean isStartElement() { + if (reader != null) { + return reader.isStartElement(); + } + return getEventType() == START_ELEMENT; + } + + public boolean isWhiteSpace() { + if (reader != null) { + return reader.isWhiteSpace(); + } + return false; + } + + /** + * By far this should be the most important method in this class this method + * changes the state of the parser + */ + public int next() throws XMLStreamException { + if (!hasNext()) { + throw new IllegalStateException("No more events"); + } + if (reader != null) { + if (!reader.hasNext()) { + this.reader = null; + } else { + // Go to the delegation mode + state = reader.next(); + return state; + } + } + if (!iterator.hasNext()) { + state = END_DOCUMENT; + current = null; + return state; + } + current = iterator.next(); + XmlNode.Type type = current.getType(); + + int itState = iterator.getState(); + if (itState == XmlNodeIterator.END) { + if (type == XmlNode.Type.ELEMENT) { + state = END_ELEMENT; + } else { + // Ignore the pop + state = next(); + } + } + if (itState == XmlNodeIterator.START) { + if (type == XmlNode.Type.ELEMENT) { + state = START_ELEMENT; + } else if (type == XmlNode.Type.CHARACTERS) { + state = CHARACTERS; + } else if (type == XmlNode.Type.READER) { + XMLStreamReader value = current.getValue(); + this.reader = new WrappingXMLStreamReader(value); + state = reader.getEventType(); + return state; + } + } + return state; + } + + /** + * TODO implement this + * + * @throws XMLStreamException + */ + public int nextTag() throws XMLStreamException { + while (true) { + int event = next(); + if (event == START_ELEMENT || event == END_ELEMENT) { + return event; + } + } + } + + public void require(int i, String ns, String localPart) throws XMLStreamException { + if (reader != null) { + reader.require(i, ns, localPart); + return; + } + int event = getEventType(); + if (event != i) { + throw new IllegalStateException("Event type is " + event + " (!=" + i + ")"); + } + QName name = getName(); + String ns1 = name.getNamespaceURI(); + String localName1 = name.getLocalPart(); + + if (ns != null && !ns.equals(ns1)) { + throw new IllegalStateException("Namespace URI is " + ns1 + " (!=" + ns + ")"); + } + + if (localPart != null && !localPart.equals(localName1)) { + throw new IllegalStateException("Local name is " + localName1 + " (!=" + localPart + ")"); + } + + } + + public boolean standaloneSet() { + return true; + } + +} diff --git a/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..10e6082b34 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,25 @@ +# 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.
+
+# implementation classes for the databindings
+org.apache.tuscany.sca.databinding.xml.DOMDataBinding;type=org.w3c.dom.Node,name=dom
+org.apache.tuscany.sca.databinding.xml.XMLStringDataBinding;type=java.lang.String,name=xml.string
+org.apache.tuscany.sca.databinding.xml.XMLGroupDataBinding;type=databinding:group
+org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding;type=java:complexType
+org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding;type=java:simpleType
+org.apache.tuscany.sca.databinding.javabeans.JavaExceptionDataBinding;type=java:exception
+org.apache.tuscany.sca.databinding.externalizable.ExternalizableDataBinding;type=java.io.Externalizable,name=externalizable
diff --git a/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBindingExtensionPoint b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBindingExtensionPoint new file mode 100644 index 0000000000..568e04f9de --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBindingExtensionPoint @@ -0,0 +1,18 @@ +# 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. + +org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint diff --git a/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..96115be404 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,40 @@ +# 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.
+
+# Implementation classes for the transformers
+org.apache.tuscany.sca.databinding.xml.InputSource2Node;source=org.xml.sax.InputSource,target=org.w3c.dom.Node,weight=80
+org.apache.tuscany.sca.databinding.xml.InputStream2Node;source=java.io.InputStream,target=org.w3c.dom.Node,weight=80
+# org.apache.tuscany.sca.databinding.javabeans.DOMNode2JavaBeanTransformer;source=org.w3c.dom.Node,target=java:complexType,weight=80000
+org.apache.tuscany.sca.databinding.xml.Node2String;source=org.w3c.dom.Node,target=java.lang.String,weight=80
+org.apache.tuscany.sca.databinding.xml.Node2XMLStreamReader;source=org.w3c.dom.Node,target=javax.xml.stream.XMLStreamReader,weight=80
+# org.apache.tuscany.sca.databinding.javabeans.JavaBean2DOMNodeTransformer;source=java:complexType,target=org.w3c.dom.Node,weight=80000
+# org.apache.tuscany.sca.databinding.javabeans.JavaBean2XMLStreamReaderTransformer;source=java:complexType,target=javax.xml.stream.XMLStreamReader,weight=79000
+org.apache.tuscany.sca.databinding.xml.Reader2Node;source=java.io.Reader,target=org.w3c.dom.Node,weight=80
+org.apache.tuscany.sca.databinding.xml.SAX2DOMPipe;source=org.xml.sax.ContentHandler,target=org.w3c.dom.Node,weight=70
+org.apache.tuscany.sca.databinding.xml.StreamDataPipe;source=java.io.OutputStream,target=java.io.InputStream,weight=90
+org.apache.tuscany.sca.databinding.xml.String2Node;source=java.lang.String,target=org.w3c.dom.Node,weight=90
+org.apache.tuscany.sca.databinding.xml.String2XMLStreamReader;source=java.lang.String,target=javax.xml.stream.XMLStreamReader,weight=90
+org.apache.tuscany.sca.databinding.xml.Writer2ReaderDataPipe;source=java.io.Writer,target=java.io.Reader,weight=90
+org.apache.tuscany.sca.databinding.xml.XMLStreamReader2Node;source=javax.xml.stream.XMLStreamReader,target=org.w3c.dom.Node,weight=80
+org.apache.tuscany.sca.databinding.xml.XMLStreamReader2String;source=javax.xml.stream.XMLStreamReader,target=java.lang.String,weight=80
+# org.apache.tuscany.sca.databinding.xml.Node2SimpleJavaType;source=org.w3c.dom.Node,target=java:simpleType,weight=80000
+# org.apache.tuscany.sca.databinding.xml.SimpleJavaType2Node;source=java:simpleType,target=org.w3c.dom.Node,weight=80000
+org.apache.tuscany.sca.databinding.xml.Source2NodeTransformer;source=javax.xml.transform.Source,target=org.w3c.dom.Node,weight=80
+org.apache.tuscany.sca.databinding.xml.Source2StringTransformer;source=javax.xml.transform.Source,target=java.lang.String,weight=80
+
+org.apache.tuscany.sca.databinding.xml.Node2SourceTransformer;source=org.w3c.dom.Node,target=javax.xml.transform.Source,weight=80
+org.apache.tuscany.sca.databinding.xml.String2SourceTransformer;source=java.lang.String,target=javax.xml.transform.Source,weight=80
diff --git a/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer new file mode 100644 index 0000000000..e02cd5c934 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer @@ -0,0 +1,26 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.xml.InputSource2SAX;source=org.xml.sax.InputSource,target=org.xml.sax.ContentHandler,weight=80 +org.apache.tuscany.sca.databinding.xml.InputStream2SAX;source=java.io.InputStream,target=org.xml.sax.ContentHandler,weight=80 +org.apache.tuscany.sca.databinding.xml.Node2OutputStream;source=org.w3c.dom.Node,target=java.io.OutputStream,weight=80 +org.apache.tuscany.sca.databinding.xml.Node2Writer;source=org.w3c.dom.Node,target=java.io.Writer,weight=80 +org.apache.tuscany.sca.databinding.xml.Reader2SAX;source=java.io.Reader,target=org.xml.sax.ContentHandler,weight=80 +org.apache.tuscany.sca.databinding.xml.Source2ResultTransformer;source=javax.xml.transform.Source,target=javax.xml.transform.Result,weight=80 +org.apache.tuscany.sca.databinding.xml.String2SAX;source=java.lang.String,target=org.xml.sax.ContentHandler,weight=80 +org.apache.tuscany.sca.databinding.xml.XMLStreamReader2SAX;source=javax.xml.stream.XMLStreamReader,target=org.xml.sax.ContentHandler,weight=70 diff --git a/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.TransformerExtensionPoint b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.TransformerExtensionPoint new file mode 100644 index 0000000000..7d8642fb1e --- /dev/null +++ b/branches/sca-android/modules/databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.TransformerExtensionPoint @@ -0,0 +1,18 @@ +# 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. + +org.apache.tuscany.sca.databinding.DefaultTransformerExtensionPoint diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/DOMHelperTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/DOMHelperTestCase.java new file mode 100644 index 0000000000..8c710062ad --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/DOMHelperTestCase.java @@ -0,0 +1,58 @@ +/* + * 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.databinding.extension; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * + * @version $Rev$ $Date$ + */ +public class DOMHelperTestCase extends TestCase { + private static final QName FOO_NAME = new QName("http://foo", "foo"); + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testDOM() throws Exception { + DocumentBuilder builder = DOMHelper.newDocumentBuilder(); + assertNotNull(builder); + Document document = DOMHelper.newDocument(); + assertNotNull(document); + Element element = DOMHelper.createElement(document, FOO_NAME); + document.appendChild(element); + QName name = DOMHelper.getQName(element); + assertEquals(FOO_NAME, name); + + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/DataBindingExtensionTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/DataBindingExtensionTestCase.java new file mode 100644 index 0000000000..f9e331fbf3 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/DataBindingExtensionTestCase.java @@ -0,0 +1,86 @@ +/* + * 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.databinding.extension; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.easymock.EasyMock; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataBindingExtensionTestCase extends TestCase { + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @SuppressWarnings("unchecked") + public void testExtension() { + DataBinding1 binding1 = new DataBinding1(Node.class); + assertEquals(Node.class.getName(), binding1.getName()); + DataType dt1 = new DataTypeImpl<Class>(Element.class, null); + assertTrue(binding1.introspect(dt1, null)); + DataType dt2 = new DataTypeImpl<Class>(String.class, null); + assertFalse(binding1.introspect(dt2, null)); + assertNull(binding1.getWrapperHandler()); + + DataBindingExtensionPoint registry = EasyMock.createMock(DataBindingExtensionPoint.class); + registry.addDataBinding(binding1); + EasyMock.expect(registry.getDataBinding(Node.class.getName())).andReturn(binding1); + EasyMock.replay(registry); + + assertNotNull(registry.getDataBinding(Node.class.getName())); + + DataBinding1 binding2 = new DataBinding1("dom", Node.class); + assertEquals("dom", binding2.getName()); + } + + private static class DataBinding1 extends BaseDataBinding { + + /** + * @param baseType + */ + public DataBinding1(Class<?> baseType) { + super(baseType); + } + + /** + * @param name + * @param baseType + */ + public DataBinding1(String name, Class<?> baseType) { + super(name, baseType); + } + + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/SimpleTypeMapperExtensionTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/SimpleTypeMapperExtensionTestCase.java new file mode 100644 index 0000000000..562c22354c --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/SimpleTypeMapperExtensionTestCase.java @@ -0,0 +1,124 @@ +/* + * 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.databinding.extension; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.easymock.EasyMock; + +/** + * + * @version $Rev$ $Date$ + */ +public class SimpleTypeMapperExtensionTestCase extends TestCase { + + private static final Map<String, Object> SAMPLE_VALUES = new HashMap<String, Object>(); + + static { + SAMPLE_VALUES.put("anyURI", "http://www.w3.com"); + SAMPLE_VALUES.put("boolean", new String[] {"true", "false", "1", "0"}); + SAMPLE_VALUES.put("byte", new String[] {"-128", "127"}); + SAMPLE_VALUES.put("date", new String[] {"2004-03-15", "2002-09-24-06:00"}); + SAMPLE_VALUES.put("dateTime", "2003-12-25T08:30:00"); + SAMPLE_VALUES.put("decimal", "3.1415292"); + SAMPLE_VALUES.put("double", new String[] {"3.1415292", "INF", "NaN"}); + SAMPLE_VALUES.put("duration", new String[] {"P8M3DT7H33M2S", "P5Y2M10DT15H"}); + SAMPLE_VALUES.put("float", new String[] {"3.1415292", "INF", "NaN"}); + SAMPLE_VALUES.put("gDay", "---11"); + if (System.getProperty("java.vendor").toUpperCase().contains("SUN") && System.getProperty("java.version").contains("1.5.0") + || + System.getProperty("java.vendor").toUpperCase().contains("APPLE INC.") && System.getProperty("java.version").contains("1.5.0")) { + + // Work around a bug in SUN JDK (including Mac OS JDK) + SAMPLE_VALUES.put("gMonth", "--02--"); + } else { + SAMPLE_VALUES.put("gMonth", "--02"); + } + SAMPLE_VALUES.put("gMonthDay", "--02-14"); + SAMPLE_VALUES.put("gYear", "1999"); + SAMPLE_VALUES.put("gYearMonth", "1972-08"); + SAMPLE_VALUES.put("ID", "id-102"); + SAMPLE_VALUES.put("IDREF", "id-102"); + SAMPLE_VALUES.put("IDREFS", "id-102 id-103 id-100"); + SAMPLE_VALUES.put("int", "77"); + SAMPLE_VALUES.put("integer", "77"); + SAMPLE_VALUES.put("long", "214"); + SAMPLE_VALUES.put("negativeInteger", "-123"); + SAMPLE_VALUES.put("nonNegativeInteger", "2"); + SAMPLE_VALUES.put("nonPositiveInteger", "0"); + SAMPLE_VALUES.put("positiveInteger", "500"); + SAMPLE_VALUES.put("short", "476"); + SAMPLE_VALUES.put("string", "Joeseph"); + SAMPLE_VALUES.put("time", "13:02:00"); + SAMPLE_VALUES.put("base64Binary", "TWFu"); + SAMPLE_VALUES.put("hexBinary", "2CDB5F"); + SAMPLE_VALUES.put("QName", "f:foo"); + SAMPLE_VALUES.put("NOTATION", "f:bar"); + } + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testMap() throws Exception { + SimpleTypeMapperImpl extension = new SimpleTypeMapperImpl(); + TransformationContext context = EasyMock.createMock(TransformationContext.class); + Map<String, Object> metaData = new HashMap<String, Object>(); + EasyMock.expect(context.getMetadata()).andReturn(metaData).anyTimes(); + EasyMock.replay(context); + + NamespaceContext namespaceContext = EasyMock.createMock(NamespaceContext.class); + EasyMock.expect(namespaceContext.getNamespaceURI(EasyMock.eq("f"))).andReturn("http://foo").anyTimes(); + EasyMock.expect(namespaceContext.getPrefix(EasyMock.eq("http://foo"))).andReturn("f").anyTimes(); + EasyMock.replay(namespaceContext); + context.getMetadata().put(NamespaceContext.class.getName(), namespaceContext); + for (TypeInfo simpleType : SimpleTypeMapperImpl.XSD_SIMPLE_TYPES.values()) { + String name = simpleType.getQName().getLocalPart(); + Object value = SAMPLE_VALUES.get(name); + if (value instanceof String[]) { + for (String s : (String[])value) { + Object obj = extension.toJavaObject(simpleType.getQName(), s, context); + String str = extension.toXMLLiteral(simpleType.getQName(), obj, context); + assertNotNull(str); + // assertTrue("[" + name + "] " + s + " " + str, + // str.contains((String) s)); + } + } else if (value instanceof String) { + Object obj = extension.toJavaObject(simpleType.getQName(), (String)value, context); + String str = extension.toXMLLiteral(simpleType.getQName(), obj, context); + assertNotNull(str); + // assertTrue("[" + name + "] " + value + " " + str, + // str.contains((String) value)); + } + } + } +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/TransformerExtensionTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/TransformerExtensionTestCase.java new file mode 100644 index 0000000000..243ac71201 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/TransformerExtensionTestCase.java @@ -0,0 +1,77 @@ +/* + * 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.databinding.extension; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.Transformer; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.easymock.EasyMock; +import org.w3c.dom.Node; + +/** + * Test case for TransformerExtension + * + * @version $Rev$ $Date$ + */ +public class TransformerExtensionTestCase extends TestCase { + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testExtension() { + MyTransformer transformer = new MyTransformer(); + assertEquals(Node.class.getName(), transformer.getSourceDataBinding()); + assertEquals(XMLStreamReader.class.getName(), transformer.getTargetDataBinding()); + assertEquals(50, transformer.getWeight()); + TransformerExtensionPoint registry = EasyMock.createMock(TransformerExtensionPoint.class); + registry.addTransformer(EasyMock.isA(Transformer.class), EasyMock.eq(true)); + EasyMock + .expect(registry.getTransformer(transformer.getSourceDataBinding(), transformer.getTargetDataBinding())) + .andReturn(transformer); + EasyMock.replay(registry); + registry.addTransformer(transformer, true); + assertSame(transformer, registry.getTransformer(transformer.getSourceDataBinding(), transformer + .getTargetDataBinding())); + } + + private static class MyTransformer extends BaseTransformer<Node, XMLStreamReader> { + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/XSDDataTypeConverterTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/XSDDataTypeConverterTestCase.java new file mode 100644 index 0000000000..07ee0b0ca4 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/extension/XSDDataTypeConverterTestCase.java @@ -0,0 +1,64 @@ +/* + * 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.databinding.extension; + +import java.math.BigInteger; +import java.util.Calendar; +import java.util.GregorianCalendar; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter; + +/** + * + * @version $Rev$ $Date$ + */ +public class XSDDataTypeConverterTestCase extends TestCase { + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testConvert() throws Exception { + XSDDataTypeConverter c = new XSDDataTypeConverter(); + assertEquals("123", c.parseAnySimpleType(c.printAnySimpleType("123"))); + assertEquals(true, c.parseBoolean(c.printBoolean(true))); + assertEquals(false, c.parseBoolean(c.printBoolean(false))); + assertEquals(123.0, c.parseDouble(c.printDouble(123.0))); + assertEquals(123.0f, c.parseFloat(c.printFloat(123.0f))); + assertEquals(64, c.parseByte(c.printByte((byte)64))); + assertEquals(123, c.parseInt(c.printInt(123))); + assertEquals(new BigInteger("123456"), c.parseInteger(c.printInteger(new BigInteger("123456")))); + assertEquals(123456L, c.parseLong(c.printLong(123456L))); + assertEquals((short)123, c.parseShort(c.printShort((short)123))); + + Calendar calendar = new GregorianCalendar(); + String s = c.printDate(calendar); + calendar = c.parseDate(s); + assertEquals(s, c.printDate(calendar)); + + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DataBindingRegistryImplTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DataBindingRegistryImplTestCase.java new file mode 100644 index 0000000000..db210683dd --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DataBindingRegistryImplTestCase.java @@ -0,0 +1,103 @@ +/* + * 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.databinding.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.easymock.EasyMock; +import org.xml.sax.ContentHandler; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataBindingRegistryImplTestCase extends TestCase { + private DataBindingExtensionPoint registry; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + registry = new DefaultDataBindingExtensionPoint(); + } + + @SuppressWarnings("unchecked") + public void testRegistry() { + DataBinding db1 = createMock(DataBinding.class); + expect(db1.getAliases()).andReturn(new String[] {"db1"}).anyTimes(); + expect(db1.getName()).andReturn(ContentHandler.class.getName()).anyTimes(); + DataType<Class> dataType1 = new DataTypeImpl<Class>(ContentHandler.class, ContentHandler.class); + expect(db1.introspect(dataType1, null)).andReturn(true); + expect(db1.introspect(EasyMock.not(EasyMock.same(dataType1)), (Operation) EasyMock.isNull())) + .andReturn(false).anyTimes(); + replay(db1); + + registry.addDataBinding(db1); + + DataBinding db2 = createMock(DataBinding.class); + expect(db2.getAliases()).andReturn(new String[] {"db2"}).anyTimes(); + expect(db2.getName()).andReturn(XMLStreamReader.class.getName()).anyTimes(); + DataType<Class> dataType2 = new DataTypeImpl<Class>(XMLStreamReader.class, XMLStreamReader.class); + expect(db2.introspect(dataType2, null)).andReturn(true); + expect(db2.introspect(EasyMock.not(EasyMock.same(dataType2)), (Operation) EasyMock.isNull())) + .andReturn(false).anyTimes(); + replay(db2); + + registry.addDataBinding(db2); + + // Lookup by name + String name = db1.getName(); + DataBinding db3 = registry.getDataBinding(name); + assertSame(db1, db3); + + // Look up by alias + DataBinding db5 = registry.getDataBinding("db1"); + assertSame(db1, db5); + + DataType dt = new DataTypeImpl<Class>(ContentHandler.class, null); + registry.introspectType(dt, null); + assertEquals(dataType1.getLogical(), ContentHandler.class); + //FIXME does not match with dynamically loaded databindings + //assertTrue(dt.getDataBinding().equalsIgnoreCase("java.lang.Object")); + + registry.removeDataBinding(name); + DataBinding db4 = registry.getDataBinding(name); + assertNull(db4); + + dt = new DataTypeImpl<Class>(null, String.class, null); + registry.introspectType(dt, null); + //FIXME does not match with dynamically loaded databindings + //assertEquals("java.lang.Object", dt.getDataBinding()); + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DataBindingTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DataBindingTestCase.java new file mode 100644 index 0000000000..7c882c0285 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DataBindingTestCase.java @@ -0,0 +1,49 @@ +/* + * 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.databinding.impl; + +import java.lang.reflect.Method; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.annotation.DataBinding; + +/** + * + * @version $Rev$ $Date$ + */ +public class DataBindingTestCase extends TestCase { + @SuppressWarnings("unused") + public void testDataType() throws Exception { + Class<Test> testClass = Test.class; + DataBinding d = testClass.getAnnotation(DataBinding.class); + Assert.assertEquals(d.value(), "sdo"); + + Method method = testClass.getMethod("test", new Class[] {Object.class}); + DataBinding d2 = method.getAnnotation(DataBinding.class); + Assert.assertEquals(d2.value(), "jaxb"); + } + + @DataBinding("sdo") + private static interface Test { + @DataBinding("jaxb") + Object test(Object object); + } +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DirectedGraphTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DirectedGraphTestCase.java new file mode 100644 index 0000000000..053e4f2a59 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/DirectedGraphTestCase.java @@ -0,0 +1,125 @@ +/* + * 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.databinding.impl; + +import java.util.Arrays; +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.impl.DirectedGraph.Edge; +import org.apache.tuscany.sca.databinding.impl.DirectedGraph.Vertex; + +/** + * + * @version $Rev$ $Date$ + */ +public class DirectedGraphTestCase extends TestCase { + private DirectedGraph<String, Object> graph; + + @Override + protected void setUp() throws Exception { + super.setUp(); + graph = new DirectedGraph<String, Object>(); + } + + public void testGraph() { + graph.addEdge("a", "b", null, 3, true); + graph.addEdge("b", "c", null, 1, true); + // graph.addEdge("a", "c", null, 8, true); + graph.addEdge("a", "d", null, 3, true); + graph.addEdge("b", "d", null, 2, true); + graph.addEdge("d", "c", null, 3, true); + graph.addEdge("c", "b", null, 1, true); + graph.addEdge("c", "d", null, 2, true); + graph.addEdge("d", "b", null, 1, true); + graph.addEdge("a", "e", null, 8, true); + graph.addEdge("c", "c", null, 2, true); + graph.addEdge("f", "g", null, 2, false); + graph.addEdge("f", "h", null, 8, true); + graph.addEdge("g", "j", null, 2, false); + graph.addEdge("j", "i", null, 2, true); + graph.addEdge("h", "i", null, 8, true); + + Vertex vertex = graph.getVertex("a"); + Assert.assertNotNull(vertex); + Assert.assertEquals(vertex.getValue(), "a"); + + Assert.assertNull(graph.getVertex("1")); + + Edge edge = graph.getEdge("a", "b"); + Assert.assertNotNull(edge); + Assert.assertEquals(edge.getWeight(), 3); + + edge = graph.getEdge("b", "a"); + Assert.assertNull(edge); + + DirectedGraph<String, Object>.Path path = graph.getShortestPath("a", "c"); + + List<DirectedGraph<String, Object>.Edge> edges = path.getEdges(); + Assert.assertEquals(edges.size(), 2); + Assert.assertEquals(edges.get(0), graph.getEdge("a", "b")); + Assert.assertEquals(edges.get(1), graph.getEdge("b", "c")); + + Assert.assertEquals(path.getWeight(), 4); + + DirectedGraph<String, Object>.Path path2 = graph.getShortestPath("b", "e"); + Assert.assertNull(path2); + + DirectedGraph<String, Object>.Path path3 = graph.getShortestPath("a", "a"); + Assert.assertTrue(path3.getWeight() == 0 && path3.getEdges().isEmpty()); + + DirectedGraph<String, Object>.Path path4 = graph.getShortestPath("c", "c"); + Assert.assertTrue(path4.getWeight() == 2 && path4.getEdges().size() == 1); + + DirectedGraph<String, Object>.Path path5 = graph.getShortestPath("f", "i"); + Assert.assertTrue(path5.getWeight() == 16 && path5.getEdges().size() == 2); + + } + + public void testSort() { + graph.addEdge("a", "b"); + graph.addEdge("a", "c"); + graph.addEdge("c", "d"); + graph.addEdge("b", "c"); + List<String> order = graph.topologicalSort(true); + assertEquals(Arrays.asList("a", "b", "c", "d"), order); + assertTrue(!graph.getVertices().isEmpty()); + + graph.addEdge("d", "a"); + try { + order = graph.topologicalSort(true); + assertTrue("Should have failed", false); + } catch (IllegalArgumentException e) { + assertTrue(true); + } + + graph.removeEdge("d", "a"); + order = graph.topologicalSort(false); + assertEquals(Arrays.asList("a", "b", "c", "d"), order); + assertTrue(graph.getVertices().isEmpty()); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/MediatorImplTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/MediatorImplTestCase.java new file mode 100644 index 0000000000..6cc8868397 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/MediatorImplTestCase.java @@ -0,0 +1,122 @@ +/* + * 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.databinding.impl; + +import java.io.StringWriter; +import java.io.Writer; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultTransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.xml.Node2String; +import org.apache.tuscany.sca.databinding.xml.Node2Writer; +import org.apache.tuscany.sca.databinding.xml.SAX2DOMPipe; +import org.apache.tuscany.sca.databinding.xml.String2SAX; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Test case for MediatorImpl + * + * @version $Rev$ $Date$ + */ +public class MediatorImplTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + "<state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + "<USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + private MediatorImpl mediator; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + DataBindingExtensionPoint dataBindingRegistry = new DefaultDataBindingExtensionPoint(); + TransformerExtensionPoint registry = new DefaultTransformerExtensionPoint(); + + registry.addTransformer(new String2SAX(), true); + registry.addTransformer(new SAX2DOMPipe(), true); + registry.addTransformer(new Node2String(), true); + registry.addTransformer(new Node2Writer(), true); + + mediator = new MediatorImpl(dataBindingRegistry, registry); + } + + private TransformationContext createTransformationContext(Class sourceType, Class targetType) { + TransformationContext context = new TransformationContextImpl(); + DataType sourceDataType = new DataTypeImpl<Class>(sourceType.getName(), sourceType, sourceType); + DataType targetDataType = new DataTypeImpl<Class>(targetType.getName(), targetType, targetType); + context.setSourceDataType(sourceDataType); + context.setTargetDataType(targetDataType); + return context; + } + + public void testTransform1() { + TransformationContext context = createTransformationContext(String.class, Node.class); + Object node = + mediator.mediate(IPO_XML, context.getSourceDataType(), context.getTargetDataType(), null); + Assert.assertTrue(node instanceof Document); + Element root = ((Document)node).getDocumentElement(); + Assert.assertEquals(root.getNamespaceURI(), "http://www.example.com/IPO"); + Assert.assertEquals(root.getLocalName(), "purchaseOrder"); + } + + public void testTransform2() { + TransformationContext context = createTransformationContext(String.class, Writer.class); + Writer writer = new StringWriter(); + mediator.mediate(IPO_XML, writer, context.getSourceDataType(), context.getTargetDataType(), null); + String str = writer.toString(); + Assert.assertTrue(str != null && str.indexOf("<shipDate>1999-12-05</shipDate>") != -1); + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/TransformerRegistryImplTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/TransformerRegistryImplTestCase.java new file mode 100644 index 0000000000..31c3fd4f00 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/TransformerRegistryImplTestCase.java @@ -0,0 +1,109 @@ +/* + * 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.databinding.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.DefaultTransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.Transformer; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; + +/** + * + * @version $Rev$ $Date$ + */ +public class TransformerRegistryImplTestCase extends TestCase { + private TransformerExtensionPoint registry; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + registry = new DefaultTransformerExtensionPoint(); + } + + public void testRegisterTransformer1() { + Transformer transformer = createMock(Transformer.class); + registry.addTransformer("a", "b", 10, transformer, true); + Transformer t = registry.getTransformer("a", "b"); + Assert.assertSame(t, transformer); + } + + public void testRegisterTransformerTransformer() { + Transformer transformer = createMock(Transformer.class); + expect(transformer.getSourceDataBinding()).andReturn("a"); + expect(transformer.getTargetDataBinding()).andReturn("b"); + expect(transformer.getWeight()).andReturn(10); + replay(transformer); + registry.addTransformer(transformer, true); + Transformer t = registry.getTransformer("a", "b"); + Assert.assertSame(t, transformer); + } + + public void testUnregisterTransformer() { + Transformer transformer = createMock(Transformer.class); + registry.addTransformer("a", "b", 10, transformer, true); + boolean result = registry.removeTransformer("a", "b"); + Assert.assertTrue(result); + Transformer t = registry.getTransformer("a", "b"); + Assert.assertNull(t); + } + + public void testGetTransformerChain() { + Transformer t1 = createMock(Transformer.class); + expect(t1.getSourceDataBinding()).andReturn("a"); + expect(t1.getTargetDataBinding()).andReturn("b"); + expect(t1.getWeight()).andReturn(10); + replay(t1); + Transformer t2 = createMock(Transformer.class); + expect(t2.getSourceDataBinding()).andReturn("b"); + expect(t2.getTargetDataBinding()).andReturn("c"); + expect(t2.getWeight()).andReturn(20); + replay(t2); + + Transformer t3 = createMock(Transformer.class); + expect(t3.getSourceDataBinding()).andReturn("a"); + expect(t3.getTargetDataBinding()).andReturn("c"); + expect(t3.getWeight()).andReturn(120); + replay(t3); + + registry.addTransformer(t1, true); + registry.addTransformer(t2, true); + registry.addTransformer(t3, true); + + List<Transformer> l1 = registry.getTransformerChain("a", "b"); + Assert.assertTrue(l1.size() == 1 && l1.get(0) == t1); + List<Transformer> l2 = registry.getTransformerChain("a", "c"); + Assert.assertTrue(l2.size() == 1 && l2.get(0) == t3); + List<Transformer> l3 = registry.getTransformerChain("a", "d"); + Assert.assertNull(l3); + + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/XMLDocumentStreamReaderTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/XMLDocumentStreamReaderTestCase.java new file mode 100644 index 0000000000..dd3d000798 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/impl/XMLDocumentStreamReaderTestCase.java @@ -0,0 +1,57 @@ +/* + * 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.databinding.impl; + +import java.io.StringReader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.databinding.xml.XMLDocumentStreamReader; +import org.apache.tuscany.sca.databinding.xml.XMLStreamReader2String; + +/** + * @version $Rev$ $Date$ + */ +public class XMLDocumentStreamReaderTestCase { + private static final String xml = "<e1><e2 a2=\"a2\"><e4>E4</e4></e2><e3 a3=\"a3\"/></e1>"; + + @org.junit.Test + public void testReader() throws Exception { + XMLInputFactory factory = XMLInputFactory.newInstance(); + XMLStreamReader r1 = factory.createXMLStreamReader(new StringReader(xml)); + XMLDocumentStreamReader r2 = new XMLDocumentStreamReader(r1); + XMLStreamReader2String t1 = new XMLStreamReader2String(); + String result = t1.transform(r2, null); + System.out.println(result); + XMLStreamReader r3 = factory.createXMLStreamReader(new StringReader(xml)); + r3.nextTag(); + r3.nextTag(); + Assert.assertEquals(XMLStreamConstants.START_ELEMENT, r3.getEventType()); + Assert.assertEquals(new QName(null, "e2"), r3.getName()); + XMLDocumentStreamReader r4 = new XMLDocumentStreamReader(r3); + result = t1.transform(r4, null); + System.out.println(result); + } +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderTestCase.java new file mode 100644 index 0000000000..bdc9690285 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderTestCase.java @@ -0,0 +1,192 @@ +/* + * 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.databinding.xml; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.custommonkey.xmlunit.Diff; + +/** + * + * @version $Rev$ $Date$ + */ +public class BeanXMLStreamReaderTestCase extends TestCase { + private static final String XML_RESULT = + "<?xml version='1.0' encoding='UTF-8'?>" + "<MyBean xmlns=\"http://xml.databinding.sca.tuscany.apache.org/\">" + + "<arr>1</arr><arr>2</arr><arr>3</arr><bean><name>Name</name></bean><i>1</i>" + + "<list>Item1</list><list>Item2</list>" + + "<map><entry><key>key1</key><value>value1</value></entry>" + + "<entry><key>key2</key><value>value2</value></entry></map>" + + "<nil xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\" />" + + "<str>ABC</str></MyBean>"; + + // The map entries can come in a different order + private static final String XML_RESULT1 = + "<?xml version='1.0' encoding='UTF-8'?>" + "<MyBean xmlns=\"http://xml.databinding.sca.tuscany.apache.org/\">" + + "<arr>1</arr><arr>2</arr><arr>3</arr><bean><name>Name</name></bean><i>1</i>" + + "<list>Item1</list><list>Item2</list>" + + "<map><entry><key>key2</key><value>value2</value></entry>" + + "<entry><key>key1</key><value>value1</value></entry></map>" + + "<nil xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\" />" + + "<str>ABC</str></MyBean>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransformation() throws Exception { + MyBean bean = new MyBean(); + bean.str = "ABC"; + bean.i = 1; + bean.arr = new long[] {1, 2, 3}; + bean.bean = new AnotherBean(); + bean.bean.setName("Name"); + bean.list.add("Item1"); + bean.list.add("Item2"); + bean.map.put("key1", "value1"); + bean.map.put("key2", "value2"); + XMLStreamReader reader = new BeanXMLStreamReaderImpl(null, bean); + XMLStreamReader2String t3 = new XMLStreamReader2String(); + String xml = t3.transform(reader, null); + Diff diff = new Diff(XML_RESULT, xml); + Diff diff1 = new Diff(XML_RESULT1, xml); + assertTrue(diff.similar() || diff1.similar()); + } + + private static class MyBean { + private long arr[]; + private String str; + private int i; + private String nil; + private List<String> list = new ArrayList(); + private AnotherBean bean; + private Map<String, String> map = new HashMap<String, String>(); + + /** + * @return the i + */ + public int getI() { + return i; + } + + /** + * @param i the i to set + */ + public void setI(int i) { + this.i = i; + } + + /** + * @return the arr + */ + public long[] getArr() { + return arr; + } + + /** + * @param arr the arr to set + */ + public void setArr(long[] arr) { + this.arr = arr; + } + + /** + * @return the str + */ + public String getStr() { + return str; + } + + /** + * @param str the str to set + */ + public void setStr(String str) { + this.str = str; + } + + /** + * @return the bean + */ + public AnotherBean getBean() { + return bean; + } + + /** + * @param bean the bean to set + */ + public void setBean(AnotherBean bean) { + this.bean = bean; + } + + public List<String> getList() { + return list; + } + + public void setList(List<String> list) { + this.list = list; + } + + public String getNil() { + return nil; + } + + public void setNil(String nil) { + this.nil = nil; + } + + public Map<String, String> getMap() { + return map; + } + + public void setMap(Map<String, String> map) { + this.map = map; + } + + } + + private static class AnotherBean { + private String name; + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/DOM2StAXTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/DOM2StAXTestCase.java new file mode 100644 index 0000000000..9e9dabcea7 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/DOM2StAXTestCase.java @@ -0,0 +1,108 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.custommonkey.xmlunit.XMLAssert; +import org.w3c.dom.Node; + +/** + * + * @version $Rev$ $Date$ + */ +public class DOM2StAXTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + private static final String CRAZY_XML = + "<p:e1 xmlns=\"http://ns0\" xmlns:p=\"http://p1\">" + "<p:e2 xmlns:p=\"http://p2\"/><e3/><e4 xmlns=\"\">E4</e4></p:e1>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransformation() throws Exception { + String2Node t1 = new String2Node(); + Node node = t1.transform(IPO_XML, null); + Node2XMLStreamReader t2 = new Node2XMLStreamReader(); + XMLStreamReader reader = t2.transform(node, null); + XMLStreamReader2String t3 = new XMLStreamReader2String(); + String xml = t3.transform(reader, null); + XMLAssert.assertXMLEqual(IPO_XML, xml); + // assertTrue(xml != null && xml.indexOf("<shipDate>1999-12-05</shipDate>") != -1); + } + + public void testTransformation2() throws Exception { + String2Node t1 = new String2Node(); + Node node = t1.transform(CRAZY_XML, null); + Node2XMLStreamReader t2 = new Node2XMLStreamReader(); + XMLStreamReader reader = t2.transform(node, null); + XMLStreamReader2String t3 = new XMLStreamReader2String(); + String xml = t3.transform(reader, null); + // System.out.println(xml); + XMLAssert.assertXMLEqual(CRAZY_XML, xml); + assertTrue(xml.contains("<p:e2 xmlns:p=\"http://p2\"")); + } + + public void testTransformation3() throws Exception { + String2Node t1 = new String2Node(); + Node node = t1.transform(IPO_XML, null); + DOMXmlNodeImpl element = new DOMXmlNodeImpl(node); + XmlTreeStreamReaderImpl reader = new XmlTreeStreamReaderImpl(element); + XMLStreamReader2String t3 = new XMLStreamReader2String(); + String xml = t3.transform(reader, null); + XMLAssert.assertXMLEqual(IPO_XML, xml); + // assertTrue(xml != null && xml.indexOf("<shipDate>1999-12-05</shipDate>") != -1); + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/DataPipeTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/DataPipeTestCase.java new file mode 100644 index 0000000000..f3b37c86db --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/DataPipeTestCase.java @@ -0,0 +1,93 @@ +/* + * 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.databinding.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.apache.tuscany.sca.databinding.impl.PipedTransformer; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Test case for DataPipe + * + * @version $Rev$ $Date$ + */ +public class DataPipeTestCase extends TestCase { + + public final void testStreamPipe() throws IOException { + byte[] bytes = new byte[] {1, 2, 3}; + DataPipeTransformer<OutputStream, InputStream> pipe = new StreamDataPipe(); + DataPipe<OutputStream, InputStream> dataPipe = pipe.newInstance(); + OutputStream os = dataPipe.getSink(); + os.write(bytes); + byte[] newBytes = new byte[16]; + int count = dataPipe.getResult().read(newBytes); + Assert.assertEquals(3, count); + for (int i = 0; i < bytes.length; i++) { + Assert.assertEquals(bytes[i], newBytes[i]); + } + } + + public final void testWriter2ReaderPipe() throws IOException { + String str = "ABC"; + Writer2ReaderDataPipe pipe = new Writer2ReaderDataPipe(); + Assert.assertSame(Writer.class, pipe.getSourceType()); + Assert.assertSame(Reader.class, pipe.getTargetType()); + DataPipe<Writer, Reader> dataPipe = pipe.newInstance(); + dataPipe.getSink().write(str); + char[] buf = new char[16]; + int count = dataPipe.getResult().read(buf); + Assert.assertEquals(3, count); + for (int i = 0; i < str.length(); i++) { + Assert.assertEquals(str.charAt(i), buf[i]); + } + } + + public final void testPiped() throws Exception { + Node2Writer node2Writer = new Node2Writer(); + Writer2ReaderDataPipe pipe = new Writer2ReaderDataPipe(); + PipedTransformer<Node, Writer, Reader> transformer = + new PipedTransformer<Node, Writer, Reader>(node2Writer, pipe); + Document document = DOMHelper.newDocument(); + Element element = document.createElementNS("http://ns1", "root"); + document.appendChild(element); + Reader reader = transformer.transform(document, null); + Assert.assertEquals(transformer.getWeight(), node2Writer.getWeight() + pipe.getWeight()); + Assert.assertEquals(transformer.getSourceDataBinding(), node2Writer.getSourceDataBinding()); + Assert.assertEquals(transformer.getTargetDataBinding(), pipe.getTargetDataBinding()); + char[] buf = new char[120]; + int count = reader.read(buf); + String xml = new String(buf, 0, count); + Assert.assertTrue(xml.contains("<root xmlns=\"http://ns1\"/>")); + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/JavaBean2XMLStreamReaderTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/JavaBean2XMLStreamReaderTestCase.java new file mode 100644 index 0000000000..3a287a5bb7 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/JavaBean2XMLStreamReaderTestCase.java @@ -0,0 +1,144 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.javabeans.JavaBean2XMLStreamReaderTransformer; +import org.custommonkey.xmlunit.XMLAssert; + +/** + * + * @version $Rev$ $Date$ + */ +public class JavaBean2XMLStreamReaderTestCase extends TestCase { + private static final String XML_RESULT = + "<?xml version='1.0' encoding='UTF-8'?>" + + "<MyBean xmlns=\"http://xml.databinding.sca.tuscany.apache.org/\">" + + "<arr>1</arr><arr>2</arr><arr>3</arr><bean><name>Name</name></bean><i>1</i><str>ABC</str>" + + "</MyBean>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransformation() throws Exception { + JavaBean2XMLStreamReaderTransformer t2 = new JavaBean2XMLStreamReaderTransformer(); + MyBean bean = new MyBean(); + bean.str = "ABC"; + bean.i = 1; + bean.arr = new long[] {1, 2, 3}; + bean.bean = new AnotherBean(); + bean.bean.setName("Name"); + XMLStreamReader reader = t2.transform(bean, null); + XMLStreamReader2String t3 = new XMLStreamReader2String(); + String xml = t3.transform(reader, null); + XMLAssert.assertXMLEqual(XML_RESULT, xml); + + } + + private static class MyBean { + private String str; + private int i; + private long arr[]; + private AnotherBean bean; + + /** + * @return the arr + */ + public long[] getArr() { + return arr; + } + + /** + * @param arr the arr to set + */ + public void setArr(long[] arr) { + this.arr = arr; + } + + /** + * @return the i + */ + public int getI() { + return i; + } + + /** + * @param i the i to set + */ + public void setI(int i) { + this.i = i; + } + + /** + * @return the str + */ + public String getStr() { + return str; + } + + /** + * @param str the str to set + */ + public void setStr(String str) { + this.str = str; + } + + /** + * @return the bean + */ + public AnotherBean getBean() { + return bean; + } + + /** + * @param bean the bean to set + */ + public void setBean(AnotherBean bean) { + this.bean = bean; + } + + } + + private static class AnotherBean { + private String name; + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/Node2StringTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/Node2StringTestCase.java new file mode 100644 index 0000000000..cc1f9375c8 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/Node2StringTestCase.java @@ -0,0 +1,39 @@ +/* + * 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.databinding.xml; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * + * @version $Rev$ $Date$ + */ +public class Node2StringTestCase extends TestCase { + public void testTransformation() throws Exception { + Document document = DOMHelper.newDocument(); + Element element = document.createElementNS("http://ns1", "test"); + document.appendChild(element); + + new Node2String().transform(document, null); + } +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/PushTransformationTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/PushTransformationTestCase.java new file mode 100644 index 0000000000..5ae0616577 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/PushTransformationTestCase.java @@ -0,0 +1,86 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.impl.PipedTransformer; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +/** + * + * @version $Rev$ $Date$ + */ +public class PushTransformationTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransformation() { + String2XMLStreamReader t1 = new String2XMLStreamReader(); + XMLStreamReader reader = t1.transform(IPO_XML, null); + XMLStreamReader2SAX t2 = new XMLStreamReader2SAX(); + PipedTransformer<XMLStreamReader, ContentHandler, Node> t3 = + new PipedTransformer<XMLStreamReader, ContentHandler, Node>(t2, new SAX2DOMPipe()); + Node node = t3.transform(reader, null); + Assert.assertNotNull(node); + Node2String t4 = new Node2String(); + String xml = t4.transform(node, null); + Assert.assertTrue(xml != null && xml.indexOf("<shipDate>1999-12-05</shipDate>") != -1); + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/StAXHelperTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/StAXHelperTestCase.java new file mode 100644 index 0000000000..9ca490f2d8 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/StAXHelperTestCase.java @@ -0,0 +1,55 @@ +/* + * 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.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.custommonkey.xmlunit.XMLAssert; + +/** + * Test Case for StAXHelper + * + * @version $Rev$ $Date$ + */ +public class StAXHelperTestCase extends TestCase { + private static final String XML = + "<a:foo xmlns:a='http://a' name='foo'><bar name='bar'>" + + "<doo a:name='doo' xmlns:a='http://doo'/>" + + "</bar></a:foo>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testHelper() throws Exception { + XMLStreamReader reader = StAXHelper.createXMLStreamReader(XML); + String xml = StAXHelper.save(reader); + XMLAssert.assertXMLEqual(XML, xml); + reader = StAXHelper.createXMLStreamReader(xml); + assertNotNull(reader); + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/TraxTransformerTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/TraxTransformerTestCase.java new file mode 100644 index 0000000000..ff6f8c1406 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/TraxTransformerTestCase.java @@ -0,0 +1,101 @@ +/* + * 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.databinding.xml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URL; + +import junit.framework.TestCase; + +import org.w3c.dom.Node; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * + * @version $Rev$ $Date$ + */ +public class TraxTransformerTestCase extends TestCase { + private URL url; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + url = getClass().getResource("foo.xml"); + } + + public void testTransformDOM() throws IOException { + InputStream is = url.openStream(); + InputStream2Node t1 = new InputStream2Node(); + Node node = t1.transform(is, null); + is.close(); + Writer writer = new StringWriter(); + Node2Writer t2 = new Node2Writer(); + t2.transform(node, writer, null); + String str = writer.toString(); + StringReader reader = new StringReader(str); + Reader2Node t3 = new Reader2Node(); + node = t3.transform(reader, null); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + Node2OutputStream t4 = new Node2OutputStream(); + t4.transform(node, os, null); + InputSource inputSource = new InputSource(new ByteArrayInputStream(os.toByteArray())); + InputSource2Node t5 = new InputSource2Node(); + node = t5.transform(inputSource, null); + } + + public void testTransformSAX() throws IOException { + MyContentHandler handler = new MyContentHandler(); + InputStream is = url.openStream(); + InputStream2SAX t1 = new InputStream2SAX(); + t1.transform(is, handler, null); + is.close(); + + String xml = "<foo xmlns=\"http://foo\">bar</foo>"; + + InputSource inputSource = new InputSource(new StringReader(xml)); + InputSource2SAX t2 = new InputSource2SAX(); + MyContentHandler handler2 = new MyContentHandler(); + t2.transform(inputSource, handler2, null); + + } + + private static class MyContentHandler extends DefaultHandler { + + @Override + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) + throws SAXException { + super.startElement(namespaceURI, localName, qName, atts); + } + + } + +} diff --git a/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderTestCase.java b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderTestCase.java new file mode 100644 index 0000000000..0463e7d9f5 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderTestCase.java @@ -0,0 +1,199 @@ +/* + * 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.databinding.xml; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; + +import org.custommonkey.xmlunit.XMLAssert; +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class XmlTreeStreamReaderTestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + private static final String XML_RESULT = + "<?xml version='1.0' encoding='UTF-8'?>" + "<p1:e1 xmlns:p1=\"http://ns\">" + + "<p2:e11 xmlns:p2=\"http://ns1\">MyText</p2:e11>" + + "<p1:e12><p1:e121 /></p1:e12>" + + "<ipo:purchaseOrder xmlns:ipo=\"http://www.example.com/IPO\" " + + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + + "xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\" orderDate=\"1999-12-01\"> " + + "<shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\"> " + + "<name>Helen Zoe</name> <street>47 Eden Street</street> " + + "<city>Cambridge</city> <postcode>CB1 1JR</postcode> </shipTo> " + + "<billTo xsi:type=\"ipo:USAddress\"> <name>Robert Smith</name> " + + "<street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> " + + "<zip>95819</zip> </billTo> <items> <item partNum=\"833-AA\"> " + + "<productName>Lapis necklace</productName> <quantity>1</quantity> " + + "<USPrice>99.95</USPrice> <ipo:comment>Want this for the holidays</ipo:comment> " + + "<shipDate>1999-12-05</shipDate> </item> </items></ipo:purchaseOrder></p1:e1>"; + private XmlNodeImpl root; + + @Before + public void setUp() throws Exception { + root = new XmlNodeImpl(); + root.name = new QName("http://ns", "e1", "p1"); + + XmlNodeImpl e11 = new XmlNodeImpl(); + e11.name = new QName("http://ns1", "e11", "p2"); + + XmlNodeImpl e12 = new XmlNodeImpl(); + e12.name = new QName("http://ns", "e12"); + + root.children.add(e11); + root.children.add(e12); + + XmlNodeImpl e121 = new XmlNodeImpl(); + e121.name = new QName("http://ns", "e121"); + e12.children.add(e121); + + XmlNodeImpl e111 = new XmlNodeImpl(); + e111.value = "MyText"; + e11.children.add(e111); + + XmlNodeImpl e13 = new XmlNodeImpl(); + e13.value = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(IPO_XML)); + root.children.add(e13); + + } + + @Test + public void testIterator() { + List<QName> elements = new ArrayList<QName>(); + XmlNodeIterator i = new XmlNodeIterator(root); + for (; i.hasNext();) { + XmlNode e = i.next(); + elements.add(e.getName()); + } + // System.out.println(elements); + QName[] names = + {new QName("http://ns", "e1"), new QName("http://ns1", "e11"), null, null, new QName("http://ns1", "e11"), + new QName("http://ns", "e12"), new QName("http://ns", "e121"), new QName("http://ns", "e121"), + new QName("http://ns", "e12"), null, null, new QName("http://ns", "e1")}; + Assert.assertEquals(Arrays.asList(names), elements); + } + + @Test + public void testReader() throws Exception { + XmlTreeStreamReaderImpl reader = new XmlTreeStreamReaderImpl(root); + XMLStreamReader2String t = new XMLStreamReader2String(); + String xml = t.transform(reader, null); + XMLAssert.assertXMLEqual(XML_RESULT, xml); + } + + private static class XmlNodeImpl implements XmlNode { + private List<XmlNode> children = new ArrayList<XmlNode>(); + private List<XmlNode> attrs = new ArrayList<XmlNode>(); + private Map<String, String> namespaces = new HashMap<String, String>(); + private QName name; + private Object value = "123"; + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#attributes() + */ + public List<XmlNode> attributes() { + return attrs; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#children() + */ + public Iterator<XmlNode> children() { + return children.iterator(); + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getName() + */ + public QName getName() { + return name; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getValue() + */ + public <T> T getValue() { + return (T)value; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#namespaces() + */ + public Map<String, String> namespaces() { + return namespaces; + } + + @Override + public String toString() { + return String.valueOf(name); + } + + public Type getType() { + if (value instanceof XMLStreamReader) { + return Type.READER; + } + return name == null ? Type.CHARACTERS : Type.ELEMENT; + } + + } +} diff --git a/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/impl/ipo.xsd b/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/impl/ipo.xsd new file mode 100644 index 0000000000..92a576fb98 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/impl/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * 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. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/impl/order.wsdl b/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/impl/order.wsdl new file mode 100644 index 0000000000..100890e10b --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/impl/order.wsdl @@ -0,0 +1,76 @@ +<?xml version="1.0"?>
+<!--
+ * 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.
+-->
+<definitions name="StockQuote" targetNamespace="http://example.com/order.wsdl" xmlns:tns="http://example.com/order.wsdl"
+ xmlns:xsd1="http://example.com/order.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://schemas.xmlsoap.org/wsdl/">
+
+ <types>
+ <schema targetNamespace="http://example.com/order.xsd" xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+ <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd"/>
+ <element name="checkOrderStatus">
+ <complexType>
+ <sequence>
+ <element name="customerId" type="string" />
+ <element name="order" type="ipo:PurchaseOrderType" />
+ <element name="flag" type="int" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="checkOrderStatusResponse">
+ <complexType>
+ <sequence>
+ <element name="status" type="string" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="note" type="string" />
+ </schema>
+ </types>
+
+ <message name="CheckOrderStatusInput1">
+ <part name="body" element="xsd1:checkOrderStatus" />
+ </message>
+
+ <message name="CheckOrderStatusOutput1">
+ <part name="body" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <message name="CheckOrderStatusInput2">
+ <part name="p1" element="xsd1:checkOrderStatus" />
+ <part name="p2" element="xsd1:note" />
+ </message>
+
+ <message name="CheckOrderStatusOutput2">
+ <part name="p1" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <portType name="OrderPortType">
+ <operation name="checkOrderStatus">
+ <input message="tns:CheckOrderStatusInput1" />
+ <output message="tns:CheckOrderStatusOutput1" />
+ </operation>
+ <operation name="checkOrderStatus2">
+ <input message="tns:CheckOrderStatusInput2" />
+ <output message="tns:CheckOrderStatusOutput2" />
+ </operation>
+ </portType>
+
+</definitions>
\ No newline at end of file diff --git a/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/xml/foo.xml b/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/xml/foo.xml new file mode 100644 index 0000000000..0ba8ade1e0 --- /dev/null +++ b/branches/sca-android/modules/databinding/src/test/resources/org/apache/tuscany/sca/databinding/xml/foo.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<f:foo xmlns:f="http://foo" name="foo"> + <b:bar xmlns:b="http://bar">bar</b:bar> +</f:foo>
\ No newline at end of file |