[wise-commits] wise SVN: r530 - in core/trunk/core/src/main/java/org/jboss/wise: tree and 1 other directories.

wise-commits at lists.jboss.org wise-commits at lists.jboss.org
Sun Feb 24 13:24:26 EST 2013


Author: alessio.soldano at jboss.com
Date: 2013-02-24 13:24:26 -0500 (Sun, 24 Feb 2013)
New Revision: 530

Added:
   core/trunk/core/src/main/java/org/jboss/wise/tree/
   core/trunk/core/src/main/java/org/jboss/wise/tree/Element.java
   core/trunk/core/src/main/java/org/jboss/wise/tree/impl/
   core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementBuilderImpl.java
   core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementImpl.java
Log:
[WISE-195] Initial tree view impl


Added: core/trunk/core/src/main/java/org/jboss/wise/tree/Element.java
===================================================================
--- core/trunk/core/src/main/java/org/jboss/wise/tree/Element.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/jboss/wise/tree/Element.java	2013-02-24 18:24:26 UTC (rev 530)
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the 
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.wise.tree;
+
+import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.util.Iterator;
+
+/**
+ * @author alessio.soldano at jboss.com
+ * 
+ */
+public interface Element extends Serializable, Cloneable {
+
+    public boolean isLeaf();
+    
+    public boolean isRemovable();
+
+    public Type getClassType();
+
+    public String getName();
+
+    public boolean isNil();
+
+    public void setNil(boolean nil);
+
+    public String getId();
+
+    public boolean isNillable();
+    
+    public boolean isGroup();
+
+    public void removeChild(String id);
+    
+    public Element getChild(String id);
+    
+    public Element getChildByName(String name);
+    
+    public Iterator<String> getChildrenIDs();
+    
+//    public Iterator<String> getChildrenIDs(boolean resolve);
+    
+    public Iterator<? extends Element> getChildren();
+    
+//    public Iterator<? extends Element> getChildren(boolean resolve);
+    
+    public String getValue();
+
+    public void setValue(String value);
+    
+    public Element getPrototype();
+
+    public Element incrementChildren();
+    
+    public int getChildrenCount();
+    
+    public boolean isLazy();
+    
+    public boolean isResolved();
+    
+    /**
+     * Every WiseTreeElement must be cloneable; this is required to handle
+     * element's add and removal into/from arrays and collections.
+     */
+    public Element clone();
+
+    /**
+     * This is required to convert a tree element into the corresponding object
+     * instance.
+     * 
+     * @return The object corresponding to this element
+     */
+    public Object toObject();
+
+}

Added: core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementBuilderImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementBuilderImpl.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementBuilderImpl.java	2013-02-24 18:24:26 UTC (rev 530)
@@ -0,0 +1,252 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the 
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.wise.tree.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.ws.Holder;
+
+import org.jboss.wise.core.client.WSDynamicClient;
+import org.jboss.wise.core.exception.WiseRuntimeException;
+import org.jboss.wise.core.utils.IDGenerator;
+import org.jboss.wise.core.utils.JavaUtils;
+import org.jboss.wise.core.utils.ReflectionUtils;
+import org.jboss.wise.tree.Element;
+
+
+/**
+ * @author alessio.soldano at jboss.com
+ * 
+ */
+public class ElementBuilderImpl {
+    
+    private WSDynamicClient client;
+    private final boolean request;
+    private final boolean useDefautValuesForNullLeaves;
+    
+    public ElementBuilderImpl(WSDynamicClient client, boolean request, boolean useDefautValuesForNullLeaves) {
+	this.client = client;
+	this.request = request;
+	this.useDefautValuesForNullLeaves = useDefautValuesForNullLeaves;
+    }
+    
+    public Element buildTree(Type type, String name, Object value, boolean nillable) {
+	return buildTree(type, name, value, nillable, null, null, Collections.synchronizedMap(new HashMap<Type, ElementImpl>()), new HashSet<Type>());
+    }
+
+    private ElementImpl buildTree(Type type, String name, Object obj, boolean nillable, Class<?> scope, String namespace, Map<Type, ElementImpl> typeMap, Set<Type> stack) {
+	if (type instanceof ParameterizedType) {
+	    ParameterizedType pt = (ParameterizedType) type;
+	    return this.buildParameterizedType(pt, name, obj, scope, namespace, typeMap, stack);
+	} else {
+	    return this.buildFromClass((Class<?>) type, name, obj, nillable, typeMap, stack);
+
+	}
+    }
+    
+    @SuppressWarnings("rawtypes")
+    private ElementImpl buildParameterizedType(ParameterizedType pt,
+	                                           String name,
+	                                           Object obj,
+	                                           Class<?> scope,
+	                                           String namespace,
+	                                           Map<Type, ElementImpl> typeMap,
+		    				   Set<Type> stack) {
+	Type firstTypeArg = pt.getActualTypeArguments()[0];
+	if (Collection.class.isAssignableFrom((Class<?>) pt.getRawType())) {
+	    ElementImpl group;
+	    if (obj != null || request) {
+		ElementImpl prototype = this.buildTree(firstTypeArg, name, null, true, null, null, typeMap, stack);
+		group = newElement(pt, name, false, prototype, false, typeMap);
+		if (obj != null) {
+		    for (Object o : (Collection) obj) {
+			ElementImpl childElement = this.buildTree(firstTypeArg, name, o, true, null, null, typeMap, stack);
+			childElement.setRemovable(true);
+			group.addChild(childElement);
+		    }
+		}
+	    } else {
+		group = newElement(pt, name, false, null, false, typeMap);
+	    }
+	    return group;
+	} else {
+	    if (obj != null && obj instanceof JAXBElement) {
+		obj = ((JAXBElement)obj).getValue();
+	    } else if (obj != null && obj instanceof Holder) {
+		obj = ((Holder)obj).value;
+	    }
+	    ElementImpl element = this.buildTree(firstTypeArg, name, obj, true, null, null, typeMap, stack);
+	    ElementImpl parameterized = newElement(pt, name, false, null, false, typeMap);
+	    parameterized.addChild(element);
+	    return parameterized;
+	}
+    }
+
+    private ElementImpl buildFromClass(Class<?> cl, String name, Object obj, boolean nillable, Map<Type, ElementImpl> typeMap, Set<Type> stack) {
+
+	if (cl.isArray()) {
+	    if (byte.class.equals(cl.getComponentType())) {
+		return newLeafElement(cl, name, obj, !nillable);
+	    }
+	    throw new WiseRuntimeException("Converter doesn't support this Object[] yet.");
+	}
+
+	if (isSimpleType(cl, client)) {
+	    return newLeafElement(cl, name, obj, !nillable);
+	} else { // complex
+	    final boolean recursionCheck = (request && obj == null); //lazy element disable till we have a value object (an actual SOAP request won't have cycles)
+	    if (recursionCheck && stack.contains(cl)) {
+		return newElement(cl, name, false, null, true, typeMap);
+	    }
+
+	    ElementImpl complex = newElement(cl, name, !nillable, null, false, typeMap);
+	    if (recursionCheck) {
+		stack.add(cl);
+	    }
+	    for (Field field : ReflectionUtils.getAllFields(cl)) {
+		XmlElement elemAnnotation = field.getAnnotation(XmlElement.class);
+		XmlElementRef refAnnotation = field.getAnnotation(XmlElementRef.class);
+		String fieldName = null;
+		String namespace = null;
+		if (elemAnnotation != null && !elemAnnotation.name().startsWith("#")) {
+		    fieldName = elemAnnotation.name();
+		}
+		if (refAnnotation != null) {
+		    fieldName = refAnnotation.name();
+		    namespace = refAnnotation.namespace();
+		}
+		if (fieldName == null) {
+		    fieldName = field.getName();
+		}
+		// String fieldName = (annotation != null &&
+		// !annotation.name().startsWith("#")) ? annotation.name() :
+		// field.getName();
+		Object fieldValue = null;
+		if (obj != null) {
+		    try {
+			Method getter = cl.getMethod(ReflectionUtils.getGetter(field), (Class[]) null);
+			fieldValue = getter.invoke(obj, (Object[]) null);
+		    } catch (Exception e) {
+			throw new WiseRuntimeException("Error calling getter method for field " + field, e);
+		    }
+		}
+		ElementImpl element = this.buildTree(field.getGenericType(), fieldName, fieldValue, true, cl, namespace, typeMap, stack);
+		complex.addChild(element);
+	    }
+	    if (recursionCheck) {
+		stack.remove(cl);
+		if (!typeMap.containsKey(cl)) {
+		    typeMap.put(cl, complex.cloneInternal());
+		}
+	    }
+	    return complex;
+	}
+    }
+    
+    protected boolean isSimpleType(Class<?> cl, WSDynamicClient client) {
+	return cl.isEnum() || cl.isPrimitive() || client.getClassLoader() != cl.getClassLoader();
+    }
+    
+    private ElementImpl newLeafElement(Class<?> classType, String name, Object value, boolean forceNotNillable) {
+	ElementImpl element = new ElementImpl(true);
+	element.setClassType(classType);
+	element.setName(name);
+	element.setId(generateNewID());
+	if (forceNotNillable) {
+	    element.enforceNotNillable();
+	} else {
+	    // primitive are not nillable, thus they can't be nil or have a null value
+	    final boolean primitive = classType.isPrimitive();
+	    element.setNillable(!primitive);
+	    element.setNil(!primitive);
+	    if (value == null && (useDefautValuesForNullLeaves || primitive)) {
+		element.setValue(getDefaultValue(classType));
+		element.setNil(false);
+	    }
+	}
+	if (value != null) {
+	    element.parseObject(value);
+	}
+	return element;
+    }
+    
+    private ElementImpl newElement(Type classType, String name, boolean forceNotNillable, ElementImpl prototype, boolean lazy, Map<Type, ElementImpl> treeTypesMap) {
+	ElementImpl element = new ElementImpl(false);
+	element.setClassType(classType);
+	element.setName(name);
+	element.setId(generateNewID());
+	if (classType instanceof ParameterizedType && Collection.class.isAssignableFrom((Class<?>) ((ParameterizedType) classType).getRawType())) {
+	    element.setPrototype(prototype);
+	    element.setGroup(true);
+	}
+	element.setClient(client);
+	element.setLazy(lazy);
+	element.setTreeTypesMap(treeTypesMap);
+	if (forceNotNillable) {
+	    element.enforceNotNillable();
+	}
+	return element;
+    }
+    
+    protected static String getDefaultValue(Class<?> cl) {
+	if (cl.isPrimitive()) {
+	    cl = JavaUtils.getWrapperType(cl);
+	}
+	String cn = cl.getName();
+	if ("java.lang.Boolean".equals(cn)) {
+	    return "false";
+	} else if ("java.lang.Byte".equals(cn)) {
+	    return "0";
+	} else if ("java.lang.Double".equals(cn)) {
+	    return "0.0";
+	} else if ("java.lang.Float".equals(cn)) {
+	    return "0.0";
+	} else if ("java.lang.Integer".equals(cn)) {
+	    return "0";
+	} else if ("java.lang.Long".equals(cn)) {
+	    return "0";
+	} else if ("java.lang.Short".equals(cn)) {
+	    return "0";
+	} else if ("java.math.BigDecimal".equals(cn)) {
+	    return "0.0";
+	} else if ("java.math.BigInteger".equals(cn)) {
+	    return "0";
+	} else if ("javax.xml.datatype.Duration".equals(cn)) {
+	    return "0";
+	} else if ("javax.xml.datatype.XMLGregorianCalendar".equals(cn)) {
+	    return "1970-01-01T00:00:00.000Z";
+	} else {
+	    return "";
+	}
+    }
+    
+    protected String generateNewID() {
+	return IDGenerator.nextVal();
+    }
+}

Added: core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementImpl.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/jboss/wise/tree/impl/ElementImpl.java	2013-02-24 18:24:26 UTC (rev 530)
@@ -0,0 +1,580 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the 
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.wise.tree.impl;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.DatatypeConverter;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import javax.xml.ws.Holder;
+
+import org.jboss.wise.core.client.WSDynamicClient;
+import org.jboss.wise.core.exception.WiseRuntimeException;
+import org.jboss.wise.core.utils.IDGenerator;
+import org.jboss.wise.core.utils.JavaUtils;
+import org.jboss.wise.core.utils.ReflectionUtils;
+import org.jboss.wise.tree.Element;
+
+/**
+ * @author alessio.soldano at jboss.com
+ */
+public class ElementImpl implements Element {
+
+    private static final long serialVersionUID = -2831618351948874761L;
+    
+    protected String id;
+    protected String name;
+    protected String value;
+
+    protected boolean nil; //whether this elements has the attribute xsi:nil set to "true"
+    protected boolean nillable = true; //for primitives and explicitly not nillable elements
+    protected boolean removable; // to be used on array elements
+    
+    private Element parent;
+    protected Type classType;
+    protected boolean isLeaf;
+    protected boolean lazy;
+    protected boolean resolved;
+    protected boolean group;
+    
+    protected Map<String, ElementImpl> children;
+    protected ElementImpl prototype;
+    
+    protected WSDynamicClient client;
+    protected Map<Type, ElementImpl> treeTypesMap;
+
+    protected ElementImpl(boolean isLeaf) {
+	this.isLeaf = isLeaf;
+	if (isLeaf) {
+	    children = Collections.emptyMap();
+	} else {
+	    children = new HashMap<String, ElementImpl>(8);
+	}
+    }
+    
+    @Override
+    public boolean isLeaf() {
+	return isLeaf;
+    }
+    
+    @Override
+    public boolean isRemovable() {
+	return removable;
+    }
+
+//    @Override
+    protected void setRemovable(boolean removable) {
+	this.removable = removable;
+    }
+
+    @Override
+    public Type getClassType() {
+	return classType;
+    }
+    
+    public void setClassType(Type classType) {
+	this.classType = classType;
+    }
+
+    @Override
+    public String getName() {
+	return name;
+    }
+
+    public void setName(String name) {
+	this.name = name;
+    }
+
+    @Override
+    public boolean isNil() {
+	return nil;
+    }
+
+    @Override
+    public void setNil(boolean nil) {
+	this.nil = nil;
+    }
+
+    @Override
+    public String getId() {
+	return id;
+    }
+    
+    protected void setId(String id) {
+	this.id = id;
+    }
+
+    @Override
+    public boolean isNillable() {
+	return nillable;
+    }
+
+    public void setNillable(boolean nillable) {
+	this.nillable = nillable;
+    }
+    
+    @Override
+    public boolean isGroup() {
+	return group;
+    }
+    
+    protected void setGroup(boolean group) {
+	this.group = group;
+    }
+
+    public Element getParent() {
+        return parent;
+    }
+
+    protected void setParent(Element parent) {
+        this.parent = parent;
+    }
+    
+    @Override
+    public String getValue() {
+	return value;
+    }
+
+    @Override
+    public void setValue(String value) {
+	checkLeaf();
+	this.value = value;
+    }
+    
+    public void parseObject(Object obj) {
+	checkLeaf();
+	if (obj == null) {
+	    this.setValue(null);
+	}
+	if (obj instanceof byte[]) {
+	    this.setValue(DatatypeConverter.printBase64Binary((byte[])obj));
+	} else {
+	    this.setValue(obj.toString());
+	}
+	this.nil = (obj == null && nillable);
+    }
+    
+    protected void checkLeaf() {
+	if (!isLeaf) {
+	    throw new UnsupportedOperationException("Element is not leaf");
+	}
+    }
+    
+    protected void setClient(WSDynamicClient client) {
+	this.client = client;
+    }
+    
+    protected void setTreeTypesMap(Map<Type, ElementImpl> treeTypesMap) {
+        this.treeTypesMap = treeTypesMap;
+    }
+
+    public void addChild(ElementImpl child) {
+	if (isLeaf) {
+	    throw new UnsupportedOperationException("Element is leaf");
+	}
+	children.put(child.getId(), child);
+	child.setParent(this);
+    }
+
+    @Override
+    public void removeChild(String id) {
+	ElementImpl child = children.remove(id);
+	if (child != null) {
+	    if (!child.isRemovable()) {
+		children.put(id, child);
+		throw new WiseRuntimeException("Element for id=" + id + " is not removable!");
+	    }
+	    child.setParent(null);
+	}
+    }
+    
+    @Override
+    public Element getChild(String id) {
+	resolveReference();
+	return children.get(id);
+    }
+    
+    @Override
+    public Element getChildByName(String name) {
+	if (group) {
+	    throw new UnsupportedOperationException("Cannot get child by name for a group element!");
+	}
+	resolveReference();
+	for (ElementImpl el : children.values()) {
+	    if (name.equals(el.getName())) {
+		return el;
+	    }
+	}
+	return null;
+    }
+    
+    @Override
+    public Iterator<String> getChildrenIDs() {
+	return this.getChildrenIDs(true);
+    }
+    
+    @Override
+    public Iterator<? extends Element> getChildren() {
+	return this.getChildren(true);
+    }
+    
+//    @Override
+    protected Iterator<String> getChildrenIDs(boolean resolve) {
+	if (resolve) {
+	    resolveReference();
+	}
+	return unmodifiableIterator(children.keySet().iterator());
+    }
+    
+//    @Override
+    protected Iterator<? extends Element> getChildren(boolean resolve) {
+	return this.getChildrenInternal(resolve);
+    }
+    
+    protected Iterator<ElementImpl> getChildrenInternal(boolean resolve) {
+	if (resolve) {
+	    resolveReference();
+	}
+	return unmodifiableIterator(children.values().iterator());
+    }
+    
+    protected void resolveReference() {
+	if (isLazy() && !isResolved()) {
+	    ElementImpl ref = treeTypesMap.get(this.classType);
+            ElementImpl component = ref.cloneInternal();
+            component.setName(this.getName());
+            addChild(component);
+            setResolved(true);
+	}
+    }
+    
+    @Override
+    public boolean isLazy() {
+	return lazy;
+    }
+    
+    protected void setLazy(boolean lazy) {
+	this.lazy = lazy;
+    }
+    
+    @Override
+    public boolean isResolved() {
+	return resolved;
+    }
+    
+    protected void setResolved(boolean resolved) {
+	this.resolved = resolved;
+    }
+    
+    @Override
+    public Element getPrototype() {
+	return prototype;
+    }
+
+    protected void setPrototype(ElementImpl prototype) {
+	this.prototype = prototype;
+    }
+    
+    @Override
+    public Element incrementChildren() {
+	if (!group) {
+	    throw new UnsupportedOperationException("Element is not a group!");
+	}
+	resolveReference();
+	ElementImpl component = prototype.cloneInternal();
+	component.setRemovable(true);
+	this.addChild(component);
+	return component;
+    }
+    
+    @Override
+    public int getChildrenCount() {
+	resolveReference();
+	return children.size();
+    }
+    
+    /**
+     * Every Element must be cloneable; this is required to handle
+     * element's add and removal into/from arrays and collections.
+     */
+    @Override
+    public Element clone() {
+	return this.cloneInternal();
+    }
+    
+    protected ElementImpl cloneInternal() {
+	ElementImpl element = new ElementImpl(isLeaf);
+	element.setId(IDGenerator.nextVal());
+	element.setName(this.name);
+	element.setNil(this.nil);
+	element.setClassType(this.classType);
+	element.setRemovable(this.isRemovable());
+	element.setNillable(this.isNillable());
+	element.setLazy(this.lazy);
+	if (isLeaf) { //simple
+	    Class<?> clazz = (Class<?>)this.classType;
+	    element.setValue(clazz.isPrimitive() ? ElementBuilderImpl.getDefaultValue(clazz) : null);
+	    element.setNil(this.isNillable()); //default to nil on simple elements
+	} else if (lazy) { //lazy
+	    element.setResolved(false); //copy into an unresolved element and do not copy child
+	} else { //complex, group
+	    for (Iterator<ElementImpl> it = this.getChildrenInternal(false); it.hasNext(); ) {
+		ElementImpl child = it.next();
+		element.addChild(child.cloneInternal());
+	    }
+	    if (this.prototype != null) {
+		element.setPrototype(this.prototype.cloneInternal());
+	    }
+	}
+	element.setGroup(this.group);
+	element.setClient(this.client);
+	element.setTreeTypesMap(this.treeTypesMap);
+	return element;
+    }
+    
+    /**
+     * This is required to convert a tree element into the corresponding object
+     * instance.
+     * 
+     * @return The object corresponding to this element
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public Object toObject() {
+	if (nil) {
+	    return null;
+	}
+	if (isLeaf) { //simple
+	    if (value == null) {
+		return null;
+	    }
+	    Class<?> cl = (Class<?>) classType;
+	    if (cl.isArray() && byte.class.equals(cl.getComponentType())) {
+		return DatatypeConverter.parseBase64Binary(value);
+	    }
+	    if (cl.isPrimitive()) {
+		cl = JavaUtils.getWrapperType(cl);
+	    }
+	    final String n = cl.getName();
+	    if ("java.lang.String".equals(n)) {
+		return new String(value);
+	    } else if ("java.lang.Boolean".equals(n)) {
+		return new Boolean(value);
+	    } else if ("java.lang.Byte".equals(n)) {
+		return new Byte(value);
+	    } else if ("java.lang.Character".equals(n)) {
+		return new Character(value.charAt(0));
+	    } else if ("java.lang.Double".equals(n)) {
+		return new Double(value);
+	    } else if ("java.lang.Float".equals(n)) {
+		return new Float(value);
+	    } else if ("java.lang.Integer".equals(n)) {
+		return new Integer(value);
+	    } else if ("java.lang.Long".equals(n)) {
+		return new Long(value);
+	    } else if ("java.lang.Short".equals(n)) {
+		return new Short(value);
+	    } else if ("java.math.BigDecimal".equals(n)) {
+		return BigDecimal.valueOf(Double.parseDouble(value));
+	    } else if ("java.math.BigInteger".equals(n)) {
+		return BigInteger.valueOf(Long.parseLong(value));
+	    } else if ("java.lang.Object".equalsIgnoreCase(n)) {
+		return (Object) value;
+	    } else if ("javax.xml.namespace.QName".equals(n)) {
+		return QName.valueOf(value);
+	    } else if ("javax.xml.datatype.Duration".equals(n)) {
+		try {
+		    return DatatypeFactory.newInstance().newDuration(Long.parseLong(value));
+		} catch (DatatypeConfigurationException e) {
+		    throw new WiseRuntimeException("Error converting element to object, type format error?", e);
+		}
+	    } else if ("javax.xml.datatype.XMLGregorianCalendar".equals(n)) {
+		try {
+		    return DatatypeFactory.newInstance().newXMLGregorianCalendar(value);
+		} catch (DatatypeConfigurationException e) {
+		    throw new WiseRuntimeException("Type format error", e);
+		}
+	    } else {
+		throw new WiseRuntimeException("Class type not supported: " + cl);
+	    }
+	} else if (group) { //group
+	    LinkedList<Object> returnList = new LinkedList<Object>();
+	    for (Iterator<ElementImpl> it = this.getChildrenInternal(false); it.hasNext();) {
+		returnList.add(it.next().toObject());
+	    }
+	    return returnList;
+	} else if (lazy) { //lazy
+	    Iterator<ElementImpl> it = getChildrenInternal(false);
+	    return it.hasNext() ? it.next().toObject() : null;
+	} else if (classType instanceof ParameterizedType) { //parameterized
+	    Class<?> parameterizedClass = (Class<?>)((ParameterizedType) classType).getRawType();
+	    Object child = getChildren(false).next().toObject();
+	    if (parameterizedClass.isAssignableFrom(JAXBElement.class)) {
+		return instanceXmlElementDecl(this.name, (Class<?>)this.parent.getClassType(), child);
+	    } else if (parameterizedClass.isAssignableFrom(Holder.class)) {
+		return instanceHolder(child);
+	    } else {
+		throw new WiseRuntimeException("Unsupported parameterized class: " + parameterizedClass);
+	    }
+	} else { //complex
+	    try {
+		Class<?> cl = (Class<?>) classType;
+		final Object obj = cl.newInstance();
+		for (Iterator<ElementImpl> it = this.getChildrenInternal(false); it.hasNext(); ) {
+		    Element child = it.next();
+		    final boolean isBoolean = isBoolean(child.getClassType());
+		    final Object childObject = child.toObject();
+		    if (childObject != null) {
+			if (child.isGroup()) {
+			    final String getter = ReflectionUtils.getterMethodName(child.getName(), isBoolean);
+			    final Method method = cl.getMethod(getter, (Class[]) null);
+			    Collection<?> col = (Collection<?>) method.invoke(obj, (Object[]) null);
+			    col.addAll((List) childObject);
+			} else {
+			    final String setter = ReflectionUtils.setterMethodName(child.getName(), isBoolean);
+			    final Type t = child.getClassType();
+			    final Method method;
+			    if (t instanceof ParameterizedType) {
+				method = cl.getMethod(setter, (Class<?>) ((ParameterizedType) t).getRawType());
+			    } else {
+				Class<?> fieldClass = (Class<?>) t;
+				if (Duration.class.isAssignableFrom(fieldClass)) {
+				    method = cl.getMethod(setter, Duration.class);
+				} else if (XMLGregorianCalendar.class.isAssignableFrom(fieldClass)) {
+				    method = cl.getMethod(setter, XMLGregorianCalendar.class);
+				} else {
+				    method = cl.getMethod(setter, fieldClass);
+				}
+			    }
+			    method.invoke(obj, childObject);
+			}
+		    }
+		}
+		return obj;
+	    } catch (Exception e) {
+		throw new WiseRuntimeException("Error converting element to object", e);
+	    }
+	}
+    }
+    
+    /**
+     * Make sure this element can't be nill and set the default value
+     * (this is to be used e.g. for main RPC/Lit parameters)
+     */
+    protected void enforceNotNillable() {
+	this.setNillable(false);
+	if (isLeaf) {
+	    this.setNil(false);
+	    this.setValue(ElementBuilderImpl.getDefaultValue((Class<?>) classType));
+	}
+    }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private Object instanceHolder(Object obj) {
+	return new Holder(obj);
+    }
+    
+    private Object instanceXmlElementDecl(String name, Class<?> scope, Object value) {
+	try {
+	    Class<?> objectFactoryClass = null;
+	    Method methodToUse = null;
+	    boolean done = false;
+	    final List<Class<?>> objectFactories = this.client.getObjectFactories();
+	    if (objectFactories != null) {
+		Method m = value instanceof Boolean ? scope.getMethod("is" + JavaUtils.capitalize(name)) : scope.getMethod("get" + JavaUtils.capitalize(name));
+		XmlElementRef ann = m.getAnnotation(XmlElementRef.class);
+		String namespace = ann != null ? ann.namespace() : null;
+		for (Iterator<Class<?>> it = objectFactories.iterator(); it.hasNext() && !done; ) {
+		    objectFactoryClass = it.next();
+		    Method[] methods = objectFactoryClass.getMethods();
+		    for (int i = 0; i < methods.length; i++) {
+			XmlElementDecl annotation = methods[i].getAnnotation(XmlElementDecl.class);
+			if (annotation != null && name.equals(annotation.name()) && (annotation.namespace() == null || annotation.namespace().equals(namespace)) && (annotation
+				.scope() == null || annotation.scope().equals(scope))) {
+			    methodToUse = methods[i];
+			    break;
+			}
+		    }
+		    if (methodToUse != null) {
+			done = true;
+		    }
+		}
+	    }
+	    if (methodToUse != null) {
+		return methodToUse.invoke(objectFactoryClass.newInstance(), new Object[] { value });
+	    } else {
+		return null;
+	    }
+	} catch (Exception e) {
+	    throw new WiseRuntimeException(e);
+	}
+    }
+    
+    private static boolean isBoolean(Type type) {
+	String sn;
+	if (type instanceof ParameterizedType) {
+	    sn = ((Class<?>) ((ParameterizedType) type).getRawType()).getSimpleName();
+	} else {
+	    sn = ((Class<?>) type).getSimpleName();
+	}
+	return "Boolean".equalsIgnoreCase(sn);
+    }
+
+    protected <T> UnmodifiableIterator<T> unmodifiableIterator(final Iterator<T> iterator) {
+	if (iterator instanceof UnmodifiableIterator) {
+	    return (UnmodifiableIterator<T>) iterator;
+	}
+	return new UnmodifiableIterator<T>() {
+	    @Override
+	    public boolean hasNext() {
+		return iterator.hasNext();
+	    }
+
+	    @Override
+	    public T next() {
+		return iterator.next();
+	    }
+	};
+    }
+
+    private static abstract class UnmodifiableIterator<E> implements Iterator<E> {
+	public UnmodifiableIterator() {
+	}
+
+	@Override
+	public final void remove() {
+	    throw new UnsupportedOperationException();
+	}
+    }
+}



More information about the wise-commits mailing list