From 5963a2d3d6860fe57afc138f095bf2d2eb5a7b80 Mon Sep 17 00:00:00 2001 From: lresende Date: Mon, 7 Oct 2013 22:23:21 +0000 Subject: Official Tuscany 2.0.1 Release git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1530096 13f79535-47bb-0310-9956-ffa450edef68 --- .../javabeans/JavaBean2XMLTransformer.java | 262 +++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 sca-java-2.x/tags/2.0.1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java (limited to 'sca-java-2.x/tags/2.0.1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java') diff --git a/sca-java-2.x/tags/2.0.1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java b/sca-java-2.x/tags/2.0.1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBean2XMLTransformer.java new file mode 100644 index 0000000000..28d716e4f7 --- /dev/null +++ b/sca-java-2.x/tags/2.0.1/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.BaseTransformer; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +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; +} -- cgit v1.2.3