private void writeResolver(List introspectables, SourceWriter writer) { writer.println("public Class resolveClass(Object object){"); writer.indent(); for (Iterator it = introspectables.iterator(); it.hasNext(); ) { BeanResolver type = (BeanResolver) it.next(); writer.println( "if( object instanceof " + type.getType().getQualifiedSourceName() + " ) return " + type.getType().getQualifiedSourceName() + ".class;"); } writer.println("throw new RuntimeException( \"Object \"+object+\"could not be resolved.\" );"); writer.outdent(); writer.println("}"); }
private void writeIntrospectables( TreeLogger logger, List introspectables, MethodWrapper[] methods, SourceWriter writer) { for (Iterator it = introspectables.iterator(); it.hasNext(); ) { BeanResolver bean = (BeanResolver) it.next(); logger.branch( TreeLogger.DEBUG, "Introspecting: " + bean.getType().getQualifiedSourceName(), null); try { if (bean.getProperties().size() == 0) { continue; } writer.print("private static BeanDescriptor "); writer.print(bean.getType().getQualifiedSourceName().replaceAll("\\.", "_")); writer.println(" = null;"); } catch (Exception e) { logger.log(TreeLogger.ERROR, "Unable to introspect class. Is class a bean?", e); } } }
private MethodWrapper[] findMethods(TreeLogger logger, List introspectables) { HashSet methods = new HashSet(); for (Iterator it = introspectables.iterator(); it.hasNext(); ) { BeanResolver info = (BeanResolver) it.next(); logger.branch( TreeLogger.DEBUG, "Method Scanning: " + info.getType().getQualifiedSourceName(), null); try { if (info.getProperties().size() == 0) { continue; } Collection<RProperty> pds = info.getProperties().values(); for (RProperty p : pds) { if (p.getReadMethod() != null) { p.getReadMethod().hashWithType = true; methods.add(p.getReadMethod()); } if (p.getWriteMethod() != null) { p.getWriteMethod().hashWithType = true; methods.add(p.getWriteMethod()); } } } catch (Exception e) { logger.log(TreeLogger.ERROR, "Unable to introspect class. Is class a bean?", e); } } MethodWrapper[] results = new MethodWrapper[methods.size()]; Iterator it = methods.iterator(); for (int i = 0; it.hasNext(); i++) { results[i] = (MethodWrapper) it.next(); } return results; }
public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { // .println("Introspector Generate."); try { this.objectType = context.getTypeOracle().getType("java.lang.Object"); } catch (NotFoundException ex) { logger.log(TreeLogger.ERROR, typeName, ex); return null; } List<BeanResolver> introspectables = this.getIntrospectableTypes(logger, context.getTypeOracle()); MethodWrapper[] methods = this.findMethods(logger, introspectables); ClassSourceFileComposerFactory mcf = new ClassSourceFileComposerFactory(this.packageName, this.methodsImplementationName); mcf.addImport(Method.class.getCanonicalName()); PrintWriter methodsPrintWriter = context.tryCreate(logger, this.packageName, this.methodsImplementationName); if (methodsPrintWriter != null) { SourceWriter methodsWriter = mcf.createSourceWriter(context, methodsPrintWriter); this.writeMethods(logger, methods, methodsWriter); methodsWriter.println("}"); context.commit(logger, methodsPrintWriter); } ClassSourceFileComposerFactory cfcf = new ClassSourceFileComposerFactory(this.packageName, this.implementationName); cfcf.addImplementedInterface(typeName); cfcf.addImport("java.util.HashMap"); cfcf.addImport(Method.class.getCanonicalName()); cfcf.addImport(com.totsp.gwittir.introspection.Property.class.getCanonicalName()); cfcf.addImport(com.totsp.gwittir.introspection.BeanDescriptor.class.getCanonicalName()); PrintWriter printWriter = context.tryCreate(logger, packageName, implementationName); if (printWriter == null) { // .println( "Introspector Generate skipped."); return packageName + "." + implementationName; } SourceWriter writer = cfcf.createSourceWriter(context, printWriter); this.writeIntrospectables(logger, introspectables, methods, writer); this.writeResolver(introspectables, writer); writer.println( "private HashMap<Class,BeanDescriptor> beanDescriptorLookup = new HashMap<Class,BeanDescriptor>();"); writer.println(); writer.println("public BeanDescriptor getDescriptor( Object object ){ "); writer.indent(); writer.println( "if( object == null ) throw new NullPointerException(\"Attempt to introspect null object\");"); writer.println( "if( object instanceof " + SelfDescribed.class.getCanonicalName() + " ) return ((SelfDescribed)object).__descriptor();"); writer.println("BeanDescriptor descriptor = beanDescriptorLookup.get(object.getClass());"); writer.println("if (descriptor!=null){"); writer.indentln("return descriptor;"); writer.outdent(); writer.println("}"); writer.println("descriptor=_getDescriptor(object);"); writer.println("beanDescriptorLookup.put(object.getClass(),descriptor);"); writer.println("return descriptor;"); writer.outdent(); writer.println("}"); writer.println("private BeanDescriptor _getDescriptor( Object object ){ "); writer.indent(); for (BeanResolver resolver : introspectables) { writer.println( "if( object instanceof " + resolver.getType().getQualifiedSourceName() + " ) {"); writer.indent(); String name = resolver.getType().getQualifiedSourceName().replaceAll("\\.", "_"); logger.log(TreeLogger.DEBUG, "Writing : " + name, null); writer.print("return " + name + " == null ? " + name + " = "); this.writeBeanDescriptor(logger, resolver, methods, writer); writer.print(": " + name + ";"); writer.outdent(); writer.println("}"); } writer.println(" throw new IllegalArgumentException(\"Unknown type\" + object.getClass() ); "); writer.outdent(); writer.println("}"); writer.println("public Object createInstance(Class clazz) {"); writer.indent(); for (BeanResolver resolver : introspectables) { boolean hasPNA = false; for (JConstructor constructor : resolver.getType().getConstructors()) { if (constructor.getParameters() == null || constructor.getParameters().length == 0 && constructor.isPublic()) { hasPNA = true; break; } if (hasPNA) { break; } } writer.println( "if(clazz.equals(" + resolver.getType().getQualifiedSourceName() + ".class)){"); writer.indent(); logger.log( TreeLogger.Type.TRACE, resolver.getType().getQualifiedSourceName() + " abstract " + resolver.getType().isAbstract() + " intf " + (resolver.getType().isInterface() != null) + " def " + resolver.getType().isDefaultInstantiable()); if (resolver.getType().isAbstract() || resolver.getType().isInterface() != null) { writer.println("throw new IllegalArgumentException(clazz+\" is abstract\");"); } else if (hasPNA) { writer.println("return new " + resolver.getType().getQualifiedSourceName() + "();"); } else { writer.println( "throw new IllegalArgumentException(clazz+\" has no public no args constructor\");"); } writer.outdent(); writer.println("}"); } writer.println(" throw new IllegalArgumentException(\"Unknown type\" +clazz ); "); writer.outdent(); writer.println("}"); writer.println("HashMap<String, Class> classes = new HashMap<String, Class>();"); writer.println("public Class forName(String className){"); writer.indent(); writer.println("Class clazz = classes.get(className);"); writer.println("if(clazz != null) return clazz;"); for (BeanResolver resolver : introspectables) { writer.println( "if(className.equals(\"" + resolver.getType().getQualifiedSourceName() + "\")){"); writer.indent(); writer.println("clazz = " + resolver.getType().getQualifiedSourceName() + ".class;"); writer.println("classes.put(className, clazz);"); writer.println("return clazz;"); writer.outdent(); writer.println("}"); } writer.println("throw new IllegalArgumentException(className+\" is not introspecable.\");"); writer.outdent(); writer.println("}"); writer.outdent(); writer.println("}"); context.commit(logger, printWriter); // .println( "Introspector Generate completed."); return packageName + "." + implementationName; }
private void writeBeanDescriptor( TreeLogger logger, BeanResolver info, MethodWrapper[] methods, SourceWriter writer) { writer.println("new BeanDescriptor() { "); writer.indent(); writer.println("private HashMap lookup;"); writer.println("private Property[] properties;"); writer.println("public Property[] getProperties(){"); writer.indent(); { writer.println("if( this.properties != null ) "); writer.indentln("return this.properties;"); writer.println("this.properties = new Property[" + (info.getProperties().size()) + "];"); Collection pds = info.getProperties().values(); String[] propertyNames = new String[pds.size()]; logger.log(TreeLogger.SPAM, "" + (pds == null), null); if (pds != null) { int i = 0; for (Iterator it = pds.iterator(); it.hasNext(); i++) { RProperty p = (RProperty) it.next(); propertyNames[i] = p.getName(); writer.println("{"); writer.indent(); writer.print("Method readMethod = "); if (p.getReadMethod() == null) { writer.println("null;"); } else { writer.println( this.packageName + "." + this.methodsImplementationName + ".METHOD_" + +this.find(methods, p.getReadMethod()) + ";"); } writer.print("Method writeMethod = "); if (p.getWriteMethod() == null) { writer.println("null;"); } else { writer.println( this.packageName + "." + this.methodsImplementationName + ".METHOD_" + +this.find(methods, p.getWriteMethod()) + ";"); } logger.log( TreeLogger.DEBUG, p.getName() + " " + p.getType().getQualifiedSourceName(), null); JType ptype = this.resolveType(p.getType()); logger.log( TreeLogger.DEBUG, p.getName() + " (Erased) " + ptype.getQualifiedSourceName(), null); writer.println( "this.properties[" + (i) + "] = new Property( \"" + p.getName() + "\", " + ((p.getType() != null) ? ptype.getQualifiedSourceName() : "Object") + ".class, readMethod, writeMethod );"); writer.outdent(); writer.println("}"); } } writer.println("return this.properties;"); } writer.outdent(); writer.println("} //end getProperties()"); writer.println("public Property getProperty( String name ) {"); writer.indent(); // TODO Rewrite this to a nested if loop using the propertyNames parameter. writer.println("Property p = null;"); writer.println("if( this.lookup != null ) {"); writer.indentln("p = (Property) lookup.get(name); "); writer.println("} else {"); writer.indent(); writer.println("this.lookup = new HashMap();"); writer.println("Property[] props = this.getProperties(); "); writer.println("for( int i=0; i < props.length; i++ ) {"); writer.indent(); writer.println("this.lookup.put( props[i].getName(), props[i] );"); writer.outdent(); writer.println("}"); writer.println("p = (Property) this.lookup.get(name);"); writer.outdent(); writer.println("}"); writer.println( "if( p == null ) throw new RuntimeException(\"Couldn't find property \"+name+\" for " + info.getType().getQualifiedSourceName() + "\");"); writer.println("else return p;"); writer.outdent(); writer.println("}"); writer.outdent(); writer.print("}"); }
protected List<BeanResolver> getIntrospectableTypes(TreeLogger logger, TypeOracle oracle) { ArrayList<BeanResolver> results = new ArrayList<BeanResolver>(); HashSet<BeanResolver> resolvers = new HashSet<BeanResolver>(); HashSet<String> found = new HashSet<String>(); try { JClassType[] types = oracle.getTypes(); for (JClassType type : types) { if (!found.contains(type.getQualifiedSourceName()) && isIntrospectable(logger, type) && (type.isInterface() == null)) { found.add(type.getQualifiedSourceName()); resolvers.add(new BeanResolver(logger, type)); } } // Do a crazy assed sort to make sure least // assignable types are at the bottom of the list results.addAll(resolvers); results.addAll(this.getFileDeclaredTypes(logger, oracle)); boolean swap = true; // .print("Ordering "+results.size()+" by heirarchy "); while (swap) { // .print("."); swap = false; for (int i = results.size() - 1; i >= 0; i--) { BeanResolver type = (BeanResolver) results.get(i); for (int j = i - 1; j >= 0; j--) { BeanResolver check = (BeanResolver) results.get(j); if (type.getType().isAssignableTo(check.getType())) { results.set(i, check); results.set(j, type); type = check; swap = true; } } } } // System.out.println(); } catch (Exception e) { logger.log(TreeLogger.ERROR, "Unable to finad Introspectable types.", e); } // for(BeanResolver rs:results){ // logger.log(TreeLogger.ERROR, rs.toString()); // } // System.out.println("Found "+results.size()+" introspectable types."); for (BeanResolver resolver : results) { logger.log( TreeLogger.Type.INFO, "Introspectable: " + resolver.getType().getQualifiedSourceName()); } logger.log(TreeLogger.Type.INFO, "Found introspectable types: " + results.size()); return results; }