From 4537071c7caf6b151c6984fad1e11dbf698f50b0 Mon Sep 17 00:00:00 2001
From: antelder
Date: Fri, 30 Oct 2009 08:29:42 +0000
Subject: Create 2.0-M4 release branch
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@831226 13f79535-47bb-0310-9956-ffa450edef68
---
.../tuscany/sca/databinding/DataBinding.java | 91 ++
.../sca/databinding/DataBindingExtensionPoint.java | 74 ++
.../apache/tuscany/sca/databinding/DataPipe.java | 46 +
.../sca/databinding/DataPipeTransformer.java | 29 +
.../DefaultDataBindingExtensionPoint.java | 261 ++++++
.../DefaultTransformerExtensionPoint.java | 321 +++++++
.../apache/tuscany/sca/databinding/Mediator.java | 153 ++++
.../tuscany/sca/databinding/PullTransformer.java | 38 +
.../tuscany/sca/databinding/PushTransformer.java | 36 +
.../tuscany/sca/databinding/SimpleTypeMapper.java | 69 ++
.../sca/databinding/TransformationContext.java | 95 +++
.../sca/databinding/TransformationException.java | 65 ++
.../tuscany/sca/databinding/Transformer.java | 51 ++
.../sca/databinding/TransformerExtensionPoint.java | 81 ++
.../tuscany/sca/databinding/WrapperHandler.java | 78 ++
.../tuscany/sca/databinding/XMLTypeHelper.java | 68 ++
.../sca/databinding/annotation/DataBinding.java | 56 ++
.../sca/databinding/annotation/DataType.java | 43 +
.../externalizable/ExternalizableDataBinding.java | 39 +
.../sca/databinding/impl/BaseDataBinding.java | 110 +++
.../sca/databinding/impl/BaseTransformer.java | 52 ++
.../sca/databinding/impl/DirectedGraph.java | 452 ++++++++++
.../databinding/impl/Group2GroupTransformer.java | 90 ++
.../sca/databinding/impl/GroupDataBinding.java | 103 +++
.../impl/Java2SimpleTypeTransformer.java | 70 ++
.../tuscany/sca/databinding/impl/MediatorImpl.java | 581 +++++++++++++
.../sca/databinding/impl/PipedTransformer.java | 70 ++
.../impl/SimpleType2JavaTransformer.java | 89 ++
.../sca/databinding/impl/SimpleTypeMapperImpl.java | 401 +++++++++
.../impl/TransformationContextImpl.java | 129 +++
.../sca/databinding/impl/XSDDataTypeConverter.java | 945 +++++++++++++++++++++
.../javabeans/DOMNode2JavaBeanTransformer.java | 98 +++
.../javabeans/Java2XMLMapperException.java | 69 ++
.../javabeans/JavaBean2DOMNodeTransformer.java | 76 ++
.../JavaBean2XMLStreamReaderTransformer.java | 68 ++
.../javabeans/JavaBean2XMLTransformer.java | 262 ++++++
.../javabeans/JavaBeansDataBinding.java | 162 ++++
.../javabeans/JavaExceptionDataBinding.java | 35 +
.../javabeans/SimpleJavaDataBinding.java | 84 ++
.../javabeans/XML2JavaBeanTransformer.java | 329 +++++++
.../javabeans/XML2JavaMapperException.java | 76 ++
.../sca/databinding/util/DataTypeHelper.java | 165 ++++
.../tuscany/sca/databinding/util/LRUCache.java | 88 ++
.../databinding/xml/BeanXMLStreamReaderImpl.java | 300 +++++++
.../sca/databinding/xml/DOMDataBinding.java | 126 +++
.../sca/databinding/xml/DOMWrapperHandler.java | 138 +++
.../sca/databinding/xml/InputSource2Node.java | 67 ++
.../sca/databinding/xml/InputSource2SAX.java | 65 ++
.../sca/databinding/xml/InputStream2Node.java | 69 ++
.../sca/databinding/xml/InputStream2SAX.java | 64 ++
.../sca/databinding/xml/Node2OutputStream.java | 68 ++
.../sca/databinding/xml/Node2SimpleJavaType.java | 45 +
.../databinding/xml/Node2SourceTransformer.java | 61 ++
.../tuscany/sca/databinding/xml/Node2String.java | 62 ++
.../tuscany/sca/databinding/xml/Node2Writer.java | 67 ++
.../sca/databinding/xml/Node2XMLStreamReader.java | 65 ++
.../tuscany/sca/databinding/xml/Reader2Node.java | 67 ++
.../tuscany/sca/databinding/xml/Reader2SAX.java | 60 ++
.../tuscany/sca/databinding/xml/SAX2DOMPipe.java | 78 ++
.../sca/databinding/xml/SimpleJavaType2Node.java | 66 ++
.../databinding/xml/Source2NodeTransformer.java | 70 ++
.../databinding/xml/Source2ResultTransformer.java | 63 ++
.../databinding/xml/Source2StringTransformer.java | 68 ++
.../sca/databinding/xml/StAXDataBinding.java | 53 ++
.../sca/databinding/xml/StreamDataPipe.java | 65 ++
.../tuscany/sca/databinding/xml/String2Node.java | 60 ++
.../tuscany/sca/databinding/xml/String2SAX.java | 61 ++
.../databinding/xml/String2SourceTransformer.java | 62 ++
.../databinding/xml/String2XMLStreamReader.java | 62 ++
.../sca/databinding/xml/Writer2ReaderDataPipe.java | 63 ++
.../sca/databinding/xml/XMLGroupDataBinding.java | 57 ++
.../sca/databinding/xml/XMLStreamReader2Node.java | 81 ++
.../sca/databinding/xml/XMLStreamReader2SAX.java | 77 ++
.../databinding/xml/XMLStreamReader2String.java | 64 ++
.../sca/databinding/xml/XMLStringDataBinding.java | 50 ++
75 files changed, 8722 insertions(+)
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBindingExtensionPoint.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipe.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipeTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultTransformerExtensionPoint.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PullTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/PushTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/SimpleTypeMapper.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationContext.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformationException.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Transformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/TransformerExtensionPoint.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/WrapperHandler.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/XMLTypeHelper.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/annotation/DataType.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/externalizable/ExternalizableDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/DirectedGraph.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Group2GroupTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/GroupDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/Java2SimpleTypeTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/PipedTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleType2JavaTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/SimpleTypeMapperImpl.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/XSDDataTypeConverter.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/DOMNode2JavaBeanTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/Java2XMLMapperException.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2DOMNodeTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLStreamReaderTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaExceptionDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/SimpleJavaDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaBeanTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaMapperException.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/DataTypeHelper.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/LRUCache.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2String.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2Writer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2XMLStreamReader.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2Node.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2SAX.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOMPipe.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleJavaType2Node.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2NodeTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2ResultTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2StringTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StreamDataPipe.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2Node.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SAX.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SourceTransformer.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2XMLStreamReader.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Writer2ReaderDataPipe.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLGroupDataBinding.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2Node.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2SAX.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2String.java
create mode 100644 branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStringDataBinding.java
(limited to 'branches/sca-java-2.0-M4/modules/databinding/src/main/java/org')
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java
new file mode 100644
index 0000000000..7c4ed35eb3
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.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;
+
+
+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();
+
+ /**
+ * 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 XML type helper for Java types
+ * @return The databinding-specific XML type helper class
+ */
+ XMLTypeHelper getXMLTypeHelper();
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBindingExtensionPoint.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBindingExtensionPoint.java
new file mode 100644
index 0000000000..2ff5d866b4
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipe.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipe.java
new file mode 100644
index 0000000000..505a810276
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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 The data binding type of the sink
+ * @param The data binding type of the result
+ *
+ * @version $Rev$ $Date$
+ */
+public interface DataPipe {
+
+ /**
+ * 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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipeTransformer.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataPipeTransformer.java
new file mode 100644
index 0000000000..1aac6d48be
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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 extends Transformer {
+
+ DataPipe newInstance();
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java
new file mode 100644
index 0000000000..19455fcd29
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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.lang.reflect.GenericArrayType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+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 ExtensionPointRegistry registry;
+ private final Map bindings = new HashMap();
+ private final List databindings = new ArrayList();
+ private static final Logger logger = Logger.getLogger(DefaultDataBindingExtensionPoint.class.getName());
+ private boolean loadedDataBindings;
+
+ public DefaultDataBindingExtensionPoint() {
+ }
+
+ public DefaultDataBindingExtensionPoint(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ }
+
+ 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 + ";name=" + dataBinding.getName() + ",lazy=" + lazy);
+ }
+ databindings.add(dataBinding);
+ bindings.put(dataBinding.getName().toLowerCase(), dataBinding);
+
+ }
+
+ public DataBinding removeDataBinding(String id) {
+ if (id == null) {
+ return null;
+ }
+ DataBinding dataBinding = bindings.remove(id.toLowerCase());
+ if (dataBinding != null) {
+ databindings.remove(dataBinding);
+ }
+ return dataBinding;
+ }
+
+ /**
+ * Dynamically load data bindings declared under META-INF/services
+ */
+ private synchronized void loadDataBindings() {
+ if (loadedDataBindings)
+ return;
+
+ // Get the databinding service declarations
+ Collection dataBindingDeclarations;
+ try {
+ dataBindingDeclarations = registry.getServiceDiscovery().getServiceDeclarations(DataBinding.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Load data bindings
+ for (ServiceDeclaration dataBindingDeclaration : dataBindingDeclarations) {
+ Map attributes = dataBindingDeclaration.getAttributes();
+ String name = attributes.get("name");
+
+ // Create a data binding wrapper and register it
+ DataBinding dataBinding = new LazyDataBinding(name, dataBindingDeclaration);
+ addDataBinding(dataBinding);
+ }
+
+ loadedDataBindings = true;
+ }
+
+ /**
+ * A data binding facade allowing data bindings to be lazily loaded and
+ * initialized.
+ */
+ private class LazyDataBinding implements DataBinding {
+
+ private String name;
+ private ServiceDeclaration dataBindingDeclaration;
+ private DataBinding dataBinding;
+
+ private LazyDataBinding(String type, ServiceDeclaration dataBindingDeclaration) {
+ this.name = type;
+ this.dataBindingDeclaration = dataBindingDeclaration;
+ }
+
+ /**
+ * Load and instantiate the data binding class.
+ *
+ * @return The data binding.
+ */
+ @SuppressWarnings("unchecked")
+ private DataBinding getDataBinding() {
+ if (dataBinding == null) {
+ try {
+ Class dataBindingClass = (Class)dataBindingDeclaration.loadClass();
+ try {
+ Constructor constructor = dataBindingClass.getConstructor();
+ dataBinding = constructor.newInstance();
+ } catch (NoSuchMethodException e) {
+ Constructor constructor =
+ dataBindingClass.getConstructor(ExtensionPointRegistry.class);
+ dataBinding = constructor.newInstance(DefaultDataBindingExtensionPoint.this.registry);
+ }
+ } 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 getName() {
+ return name;
+ }
+
+ 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();
+ Type genericComponentType = componentType;
+ if(dataType.getGenericType() instanceof GenericArrayType) {
+ genericComponentType = ((GenericArrayType) dataType.getGenericType()).getGenericComponentType();
+ }
+ DataType logical = new DataTypeImpl(dataType.getDataBinding(), componentType, genericComponentType, 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(JavaBeansDataBinding.NAME, value.getClass(), XMLType.UNKNOWN);
+ }
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultTransformerExtensionPoint.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultTransformerExtensionPoint.java
new file mode 100644
index 0000000000..39889b1e97
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultTransformerExtensionPoint.java
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+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 ExtensionPointRegistry registry;
+ private final DirectedGraph
+ */
+ public static final class HexBinary {
+ private HexBinary() {
+ }
+
+ /**
+ * Converts the string pValue 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 pHexBinary 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);
+ }
+ }
+
+ /**
+ *
+ * An instance of {@link java.text.Format}, which may be used to parse and format xs:dateTime values.
+ *
+ */
+ 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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/DOMNode2JavaBeanTransformer.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/DOMNode2JavaBeanTransformer.java
new file mode 100644
index 0000000000..fbca9b0444
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/DOMNode2JavaBeanTransformer.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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 {
+
+ @Override
+ public Node getRootElement(Node element) throws XML2JavaMapperException {
+ if (element instanceof Document) {
+ return ((Document)element).getDocumentElement();
+ } else {
+ return element;
+ }
+
+ }
+
+ @Override
+ public Iterator getChildElements(Node parent) throws XML2JavaMapperException {
+ NodeList nodeList = parent.getChildNodes();
+ List nodeArrayList = new ArrayList(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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/Java2XMLMapperException.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/Java2XMLMapperException.java
new file mode 100644
index 0000000000..5dc13bd60b
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2DOMNodeTransformer.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2DOMNodeTransformer.java
new file mode 100644
index 0000000000..f582499b70
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2DOMNodeTransformer.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;
+
+import org.apache.tuscany.sca.common.xml.dom.DOMHelper;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+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 {
+
+ public static final String COLON = ":";
+ private DOMHelper helper;
+
+ public JavaBean2DOMNodeTransformer(ExtensionPointRegistry registry) {
+ super();
+ helper = DOMHelper.getInstance(registry);
+ }
+
+ @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 helper.newDocument().createElementNS(qName.getNamespaceURI(), qualifedName);
+ }
+
+ @Override
+ public void appendText(Node parentElement, String textData) throws Java2XMLMapperException {
+ Document document = helper.newDocument();
+ Node textNode;
+ if (textData != null) {
+ textNode = document.createTextNode(textData);
+ } else {
+ Attr nil = document.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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLStreamReaderTransformer.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 implements
+ PullTransformer {
+
+ 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 getSourceType() {
+ return Object.class;
+ }
+
+ @Override
+ protected Class getTargetType() {
+ return XMLStreamReader.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 50;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java
new file mode 100644
index 0000000000..b94b944a98
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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 extends BaseTransformer implements
+ PullTransformer {
+
+ 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 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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java
new file mode 100644
index 0000000000..4981699792
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.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.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 java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Logger;
+
+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 {
+ private final static Logger logger = Logger.getLogger(JavaBeansDataBinding.class.getName());
+ /**
+ * 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 if (arg instanceof Cloneable) {
+ Method clone;
+ try {
+ clone = arg.getClass().getMethod("clone");
+ try {
+ return clone.invoke(arg, (Object[])null);
+ } catch (InvocationTargetException e) {
+ if (e.getTargetException() instanceof CloneNotSupportedException) {
+ // Ignore
+ } else {
+ throw new IllegalArgumentException(e);
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ } catch (NoSuchMethodException e) {
+ // Ignore it
+ }
+ }
+ // return arg;
+ logger.warning("Argument type '" + arg.getClass().getName()
+ + "' is not Serializable or Cloneable. Pass-by-value is skipped.");
+ return arg;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Pass-by-value is not supported for the given object: " + arg.getClass()
+ .getName(), 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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaExceptionDataBinding.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaExceptionDataBinding.java
new file mode 100644
index 0000000000..6886462ac8
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/SimpleJavaDataBinding.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/SimpleJavaDataBinding.java
new file mode 100644
index 0000000000..b8b97d4425
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/SimpleJavaDataBinding.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.javabeans;
+
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.databinding.SimpleTypeMapper;
+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";
+ private SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl();
+
+ public SimpleJavaDataBinding(ExtensionPointRegistry registry) {
+ super(NAME, Object.class);
+// UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class);
+// this.simpleTypeMapper = utilityExtensionPoint.getUtility(SimpleTypeMapper.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))) {
+ 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 = simpleTypeMapper.getXMLType(cls);
+ type.setLogical(new XMLType(elementName, typeInfo == null ? null : typeInfo.getQName()));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaBeanTransformer.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaBeanTransformer.java
new file mode 100644
index 0000000000..6a30605f0f
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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 extends BaseTransformer implements
+ PullTransformer {
+
+ 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 && mapper.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 createJavaObject(T element, Class javaType, TransformationContext context)
+ throws XML2JavaMapperException {
+ if (isTextOnly(element)) {
+ return (L) mapper.toJavaObject(mapper.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> arrayFields = new Hashtable>();
+ Map> arraySetters = new Hashtable>();
+
+ for (Iterator 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> arrayFields,
+ TransformationContext context) throws IllegalAccessException {
+ Class> javaFieldType = (Class>) javaField.getType();
+
+ if (javaFieldType.isArray()) {
+ Class> componentType = javaFieldType.getComponentType();
+ List fldValueArray = arrayFields.get(javaField);
+ if (fldValueArray == null) {
+ fldValueArray = new ArrayList();
+ 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> 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 setterValueArray = arraySetters.get(aMethod);
+ if (setterValueArray == null) {
+ setterValueArray = new ArrayList();
+ 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> arrayFields,
+ Map> 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 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 getTargetType() {
+ return Object.class;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return JavaBeansDataBinding.NAME;
+ }
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaMapperException.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/XML2JavaMapperException.java
new file mode 100644
index 0000000000..ae06d68e67
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/DataTypeHelper.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/DataTypeHelper.java
new file mode 100644
index 0000000000..847fcf226c
--- /dev/null
+++ b/branches/sca-java-2.0-M4/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 final class DataTypeHelper {
+ private DataTypeHelper() {
+ }
+
+ /**
+ * Find all classes referenced by this data type though java generics
+ * @param d
+ * @return
+ */
+ public static Set> findClasses(DataType d) {
+ Set> classes = new HashSet>();
+ Set visited = new HashSet();
+ findClasses(d, classes, visited);
+ return classes;
+ }
+
+ private static void findClasses(DataType d, Set> classes, Set 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> classSet, Set 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 getDataTypes(Interface intf, boolean useWrapper) {
+ List dataTypes = new ArrayList();
+ for (Operation op : intf.getOperations()) {
+ getDataTypes(dataTypes, op, useWrapper);
+ }
+ return dataTypes;
+ }
+
+ /**
+ * Get all the data types in the operation
+ * @param op The operation
+ * @param useWrapper Use wrapper classes?
+ * @return A list of DataTypes
+ */
+ public static List getDataTypes(Operation op, boolean useWrapper) {
+ List dataTypes = new ArrayList();
+ getDataTypes(dataTypes, op, useWrapper);
+ return dataTypes;
+ }
+
+ private static void getDataTypes(List 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 dt3 : op.getFaultTypes()) {
+ DataType dt4 = dt3.getLogical();
+ if (dt4 != null) {
+ dataTypes.add(dt4);
+ }
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/util/LRUCache.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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
+ * @param
+ */
+
+public class LRUCache extends LinkedHashMap {
+ 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 LRUCache 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 - true for access-order,
+ * false 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 eldest) {
+ return size() > maxCacheSize;
+ }
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java
new file mode 100644
index 0000000000..ed59911a0b
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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.common.xml.stax.reader.SimpleXmlNodeImpl;
+import org.apache.tuscany.sca.common.xml.stax.reader.XmlNode;
+import org.apache.tuscany.sca.common.xml.stax.reader.XmlTreeStreamReaderImpl;
+import org.apache.tuscany.sca.databinding.SimpleTypeMapper;
+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 COMPARATOR = new Comparator() {
+ 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 SimpleTypeMapper 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 MAPPER.getXMLType(javaType) != null;
+ }
+
+ private static String getStringValue(Object o) {
+ if (o == null) {
+ return null;
+ }
+ TypeInfo info = MAPPER.getXMLType(o.getClass());
+ if (info != null) {
+ return MAPPER.toXMLLiteral(info.getQName(), o, null);
+ } else {
+ return String.valueOf(o);
+ }
+ }
+
+ @Override
+ public Iterator 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 entries = new ArrayList();
+ 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 accessorMap = getAccessors(value);
+ List accessorList = new ArrayList(accessorMap.values());
+ Collections.sort(accessorList, COMPARATOR);
+
+ List props = new ArrayList();
+ 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 getAccessors(Object target) throws Exception {
+ if (target == null) {
+ return Collections.emptyMap();
+ }
+ Map map = new HashMap();
+ 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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java
new file mode 100644
index 0000000000..ed0b5c9923
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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.common.xml.dom.DOMHelper;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+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.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+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 ROOT_NAMESPACE = "http://tuscany.apache.org/xmlns/sca/databinding/dom/1.0";
+ public static final QName ROOT_ELEMENT = new QName(ROOT_NAMESPACE, "root");
+
+ private DOMHelper domHelper;
+
+ public DOMDataBinding(ExtensionPointRegistry registry) {
+ super(NAME, Node.class);
+ this.domHelper = DOMHelper.getInstance(registry);
+ }
+
+ @Override
+ public WrapperHandler getWrapperHandler() {
+ return new DOMWrapperHandler(domHelper);
+ }
+
+ @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;
+ }
+
+ /**
+ * @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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java
new file mode 100644
index 0000000000..4ce5dc6c69
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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 org.apache.tuscany.sca.common.xml.dom.DOMHelper;
+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.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 {
+ private DOMHelper domHelper;
+
+ public DOMWrapperHandler(DOMHelper domHelper) {
+ super();
+ this.domHelper = domHelper;
+ }
+
+ public Node create(Operation operation, boolean input) {
+
+ 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);
+ }
+
+ public void setChildren(Node wrapper,
+ Object[] childObjects,
+ Operation operation, boolean input) {
+ List 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 childElements = input? operation.getWrapper().getInputChildElements():
+ operation.getWrapper().getOutputChildElements();
+ if (wrapper.getNodeType() == Node.DOCUMENT_NODE) {
+ wrapper = ((Document)wrapper).getDocumentElement();
+ }
+ List elements = new ArrayList();
+ 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 wrapperType =
+ new DataTypeImpl(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 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 names = new HashSet();
+ 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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 implements
+ PullTransformer {
+ 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 getSourceType() {
+ return InputSource.class;
+ }
+
+ @Override
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 implements
+ PushTransformer {
+
+ 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 getSourceType() {
+ return InputSource.class;
+ }
+
+ @Override
+ public Class getTargetType() {
+ return ContentHandler.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 implements
+ PullTransformer {
+ 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 getSourceType() {
+ return InputStream.class;
+ }
+
+ @Override
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 implements
+ PushTransformer {
+ 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 getSourceType() {
+ return InputStream.class;
+ }
+
+ @Override
+ public Class getTargetType() {
+ return ContentHandler.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 implements
+ PushTransformer {
+ 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 getSourceType() {
+ return Node.class;
+ }
+
+ @Override
+ protected Class getTargetType() {
+ return OutputStream.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 {
+
+ @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-java-2.0-M4/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java b/branches/sca-java-2.0-M4/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-java-2.0-M4/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 implements
+ PullTransformer {
+
+ public Source transform(Node source, TransformationContext context) {
+ try {
+ return new DOMSource(source);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class getSourceType() {
+ return Node.class;
+ }
+
+ @Override
+ protected Class