summaryrefslogtreecommitdiffstats
path: root/sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java')
-rw-r--r--sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java236
1 files changed, 236 insertions, 0 deletions
diff --git a/sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java b/sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java
new file mode 100644
index 0000000000..bb5c2561d8
--- /dev/null
+++ b/sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java
@@ -0,0 +1,236 @@
+/**
+ *
+ * Copyright 2005 BEA Systems Inc.
+ * Copyright 2005 International Business Machines Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tuscany.sdo.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import javax.xml.namespace.QName;
+
+import org.osoa.sdo.DuplicateTypeException;
+import org.osoa.sdo.Property;
+import org.osoa.sdo.Type;
+import org.osoa.sdo.helper.TypeHelper;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TypeHelperImpl implements TypeHelper {
+ private final Map<java.lang.reflect.Type, Type<?>> typesByClass;
+ private final Map<QName, Type<?>> typesByName;
+ private final ProxyClassLoader cl;
+
+ @SuppressWarnings({"ClassLoader2Instantiation"})
+ public TypeHelperImpl(ClassLoader cl) {
+ this.cl = new ProxyClassLoader(cl);
+ typesByName = new HashMap<QName, Type<?>>();
+ typesByClass = new HashMap<java.lang.reflect.Type, Type<?>>();
+ mapType(DataTypeImpl.BOOLEAN);
+ mapType(DataTypeImpl.BYTE);
+ mapType(DataTypeImpl.BYTES);
+ mapType(DataTypeImpl.CHARACTER);
+ mapType(DataTypeImpl.DATE);
+ mapType(DataTypeImpl.DOUBLE);
+ mapType(DataTypeImpl.FLOAT);
+ mapType(DataTypeImpl.INT);
+ mapType(DataTypeImpl.LONG);
+ mapType(DataTypeImpl.SHORT);
+ mapType(DataTypeImpl.STRING);
+
+ mapType(DataTypeImpl.BOOLEAN_OBJECT);
+ mapType(DataTypeImpl.CHARACTER_OBJECT);
+ }
+
+ private void mapType(Type<?> type) {
+ typesByName.put(type.getName(), type);
+
+ java.lang.reflect.Type javaType = type.getJavaType();
+ if (javaType != null) {
+ typesByClass.put(javaType, type);
+ }
+ }
+
+ public <T> Type<T> define(Class<T> interfaceClass) {
+ if (typesByClass.containsKey(interfaceClass)) {
+ throw new DuplicateTypeException(interfaceClass.getName());
+ }
+
+ String namespace;
+ String name;
+ org.osoa.sdo.annotation.Type ann = interfaceClass.getAnnotation(org.osoa.sdo.annotation.Type.class);
+ if (ann != null) {
+ namespace = ann.namespace();
+ name = ann.name();
+ } else {
+ namespace = Type.JAVA_NAMESPACE;
+ name = interfaceClass.getName();
+ }
+ return define(new QName(namespace, name), interfaceClass);
+ }
+
+ public <T> Type<T> define(QName typeName, Class<T> interfaceClass) {
+ if (!interfaceClass.isInterface()) {
+ throw new IllegalArgumentException("Not an interface: " + interfaceClass);
+ }
+
+ Method[] methods = interfaceClass.getMethods();
+ Map<String, Property> props = new LinkedHashMap<String, Property>(methods.length >> 1);
+ for (Method method : methods) {
+ String methodName = method.getName();
+ Class<?>[] params = method.getParameterTypes();
+ String propName;
+ java.lang.reflect.Type propType;
+ if (Void.TYPE.equals(method.getReturnType()) &&
+ methodName.startsWith("set") &&
+ methodName.length() > 3 &&
+ params.length == 1) {
+ propName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
+ propType = params[0];
+ } else if (Boolean.TYPE.equals(method.getReturnType()) &&
+ methodName.startsWith("is") &&
+ methodName.length() > 2 &&
+ params.length == 0) {
+ propName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
+ propType = Boolean.TYPE;
+ } else if (!Void.TYPE.equals(method.getReturnType()) &&
+ methodName.startsWith("get") &&
+ methodName.length() > 3 &&
+ params.length == 0) {
+ propName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
+ propType = method.getGenericReturnType();
+ } else {
+ throw new IllegalArgumentException("Non-accessor method on interface: " + method);
+ }
+
+ defineProperty(props, propName, propType);
+ }
+ return define(typeName, interfaceClass, new ArrayList(props.values()));
+ }
+
+ private void defineProperty(Map<String, Property> props, String propName, java.lang.reflect.Type propType) {
+ Property<?> prop = props.get(propName);
+ if (prop != null) {
+ /* TODO should check this
+ if (!propClass.equals(prop.getType().getInstanceClass())) {
+ throw new IllegalArgumentException("set/get types do not match for property: " + propName);
+ }
+ */
+ return;
+ }
+
+ int index = props.size();
+
+ if (propType instanceof Class<?>) {
+ prop = getPropertyFromClass(propName, index, propType);
+ } else if (propType instanceof ParameterizedType) {
+ prop = getPropertyFromParameterizedType(propName, index, propType);
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ props.put(propName, prop);
+ }
+
+ private Property<?> getPropertyFromParameterizedType(String propName, int index, java.lang.reflect.Type propType) {
+ ParameterizedType parameterizedType = (ParameterizedType) propType;
+ if (List.class.equals(parameterizedType.getRawType())) {
+ java.lang.reflect.Type actualPropType = parameterizedType.getActualTypeArguments()[0];
+ if (!(actualPropType instanceof Class<?>)) {
+ throw new IllegalArgumentException("Actual type of list property must not be generic: " + propName);
+ }
+ Class<?> propClass = (Class<?>) actualPropType;
+ Type<?> type = getType(propClass);
+ if (type == null) {
+ type = define(propClass);
+ }
+ return new ListPropertyImpl(propName, type, parameterizedType,index);
+ } else {
+ throw new IllegalArgumentException("Invalid generic type: " + parameterizedType);
+ }
+ }
+
+ private Property<?> getPropertyFromClass(String propName, int index, java.lang.reflect.Type propType) {
+ Class<?> propClass = (Class<?>) propType;
+ if (propClass.isArray() && !byte[].class.equals(propClass)) {
+ throw new IllegalArgumentException("Property cannot be an array type: " + propName);
+ }
+
+ Type<?> type = getType(propClass);
+ if (type == null) {
+ type = define(propClass);
+ }
+ return new PropertyImpl(propName, type, index);
+ }
+
+ private <T> Type<T> define(QName typeName, Class<T> instanceClass, List<Property> properties) {
+ if (typeName == null) {
+ throw new IllegalArgumentException("typeName is null");
+ }
+ String namespace = typeName.getNamespaceURI();
+ String name = typeName.getLocalPart();
+ if (namespace == null || Type.SDO_NAMESPACE.equals(namespace)) {
+ throw new IllegalArgumentException("Invalid namespace: " + namespace);
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("name is null");
+ }
+ if (Type.JAVA_NAMESPACE.equals(namespace) && !instanceClass.getName().equals(name)) {
+ throw new IllegalArgumentException("in Java namespace, name must equal instanceClass name");
+ }
+
+ SDOInstanceFactory<T> instanceFactory = new SDOInstanceFactory<T>();
+ Type<T> type = new TypeImpl<T>(typeName, instanceClass, properties, instanceFactory);
+
+ SDOGenerator gen = new SDOGenerator(instanceClass);
+ for (Property<?> property : properties) {
+ gen.addProperty(property);
+ }
+ byte[] bytes = gen.toByteArray();
+// dumpClass(typeName.getLocalPart(), bytes);
+ Class<T> implementationClass = (Class<T>) cl.addProxy(null, bytes);
+ instanceFactory.setImplementationClass(implementationClass);
+
+ mapType(type);
+ return type;
+ }
+
+ public <T> Type<T> getType(Class<T> interfaceClass) {
+ return (Type<T>) typesByClass.get(interfaceClass);
+ }
+
+ public Type<?> getType(QName name) {
+ return typesByName.get(name);
+ }
+
+ private static void dumpClass(String name, byte[] bytes) {
+ File file = new File("/tmp/dump/" + name.replace('.', '/') + ".class");
+ file.getParentFile().mkdirs();
+ try {
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(bytes);
+ fos.close();
+ } catch (IOException e) {
+ }
+ }
+}