//package org.jvnet.jaxb2_commons.plugin.elementwrapper; // //import java.io.File; //import java.io.FileOutputStream; //import java.io.FileReader; //import java.io.IOException; //import java.io.LineNumberReader; //import java.io.PrintWriter; //import java.util.ArrayList; //import java.util.Collection; //import java.util.HashMap; //import java.util.HashSet; //import java.util.Iterator; //import java.util.List; //import java.util.Map; //import java.util.Set; // //import javax.xml.bind.annotation.XmlElement; //import javax.xml.bind.annotation.XmlElementWrapper; // //import org.xml.sax.ErrorHandler; // // // //import com.sun.codemodel.JAnnotationUse; //import com.sun.codemodel.JClass; //import com.sun.codemodel.JDefinedClass; //import com.sun.codemodel.JExpr; //import com.sun.codemodel.JFieldVar; //import com.sun.codemodel.JMethod; //import com.sun.codemodel.JMod; //import com.sun.codemodel.JPackage; //import com.sun.tools.xjc.BadCommandLineException; //import com.sun.tools.xjc.Options; //import com.sun.tools.xjc.Plugin; //import com.sun.tools.xjc.model.CClassInfo; //import com.sun.tools.xjc.model.CClassInfoParent; //import com.sun.tools.xjc.model.CElementPropertyInfo; //import com.sun.tools.xjc.model.CPropertyInfo; //import com.sun.tools.xjc.model.CTypeInfo; //import com.sun.tools.xjc.model.Model; //import com.sun.tools.xjc.outline.ClassOutline; //import com.sun.tools.xjc.outline.FieldOutline; //import com.sun.tools.xjc.outline.Outline; //import com.sun.tools.xjc.outline.PackageOutline; //import com.sun.xml.bind.v2.model.core.ClassInfo; // //public class ElementWrapperPlugin1 extends Plugin //{ // // protected Map<String, Candidate> candidates = null; // protected File includeFile = null; // protected Set<String> include = null; // protected File excludeFile = null; // protected Set<String> exclude = null; // protected File summaryFile = null; // protected PrintWriter summary = null; // protected boolean debugMode = false; // protected boolean verbose = false; // @SuppressWarnings("unchecked") // protected Class interfaceClass = java.util.List.class; // @SuppressWarnings("unchecked") // protected Class collectionClass = java.util.ArrayList.class; // protected Instantiation instantiation = Instantiation.EARLY; // protected boolean deleteCandidates = false; // protected String factoryClassName = "ObjectFactory"; // protected String debugClassName = "JAXBDebug"; // // public ElementWrapperPlugin1() // { // } // // @Override // public String getOptionName() // { // return "Xxew"; // } // // @Override // public String getUsage() // { // return " -Xxew: Replace collection types with fields having the @XmlElementWrapper and @XmlElement annotations."; // } // // @Override // public void onActivated(Options opts) throws BadCommandLineException // { // debugMode = opts.debugMode; // verbose = opts.verbose; // // // If we are in debug mode, report... // writeDebug("JAXB Compilation started (onActivated):"); // writeDebug("\tbuildId :\t" + Options.getBuildID()); // writeDebug("\tdefaultPackage :\t" + opts.defaultPackage); // writeDebug("\tdefaultPackage2:\t" + opts.defaultPackage2); // writeDebug("\tquiet :\t" + opts.quiet); // writeDebug("\tdebug :\t" + opts.debugMode); // writeDebug("\ttargetDir :\t" + opts.targetDir); // writeDebug("\tverbose :\t" + opts.verbose); // writeDebug("\tGrammars :\t" + opts.getGrammars().length); // for (int i = 0; i < opts.getGrammars().length; i++) // writeDebug("\t [" + i + "]: " + opts.getGrammars()[i].getSystemId()); // } // // @Override // public int parseArgument(Options opt, String[] args, int i) throws BadCommandLineException, // IOException // { // // int recognized = 0; // String filename; // // String arg = args[i]; // writeDebug("Argument[" + i + "] = " + arg); // // if (arg.startsWith("-delete")) // { // recognized++; // deleteCandidates = true; // } // else if (arg.startsWith("-include")) // { // recognized++; // include = new HashSet<String>(); // // if (arg.length() > 8) // { // filename = arg.substring(8).trim(); // } // else // { // filename = args[i + 1]; // recognized++; // } // includeFile = new File(filename); // readCandidates(includeFile, include); // } // else if (arg.startsWith("-exclude")) // { // recognized++; // exclude = new HashSet<String>(); // // if (arg.length() > 8) // { // filename = arg.substring(8).trim(); // } // else // { // filename = args[i + 1]; // recognized++; // } // excludeFile = new File(filename); // readCandidates(excludeFile, exclude); // } // else if (arg.startsWith("-summary")) // { // recognized++; // if (arg.length() > 8) // { // filename = arg.substring(8).trim(); // } // else // { // filename = args[i + 1]; // recognized++; // } // // summaryFile = new File(filename); // summary = new PrintWriter(new FileOutputStream(summaryFile)); // } // else if (arg.startsWith("-collection")) // { // String ccn; // // recognized++; // if (arg.length() > 11) // { // ccn = arg.substring(11).trim(); // } // else // { // ccn = args[i + 1]; // recognized++; // } // try // { // collectionClass = Class.forName(ccn); // } // catch (ClassNotFoundException e) // { // throw new BadCommandLineException("-collection " + ccn + ": Class not found."); // } // } // else if (arg.startsWith("-instantiate")) // { // String instantiate; // recognized++; // // if (arg.length() > 12) // { // instantiate = arg.substring(12).trim().toUpperCase(); // } // else // { // instantiate = args[i + 1].trim().toUpperCase(); // recognized++; // } // instantiation = Instantiation.valueOf(instantiate); // } // else // { // //throw new BadCommandLineException("Invalid argument " + arg); // } // // // // return recognized; // } // // // @Override // public void postProcessModel(Model model, ErrorHandler errorHandler) // { // super.postProcessModel(model, errorHandler); // } // // @Override // public boolean run(Outline model, Options opt, ErrorHandler errorHandler) // { // int candidateCount = 0; // int modificationCount = 0; // int deletionCount = 0; // // JDefinedClass implementationClass; // Candidate candidate; // String fieldName; // String typeName; // Collection<JMethod> methodsToRemove; // // writeDebug("JAXB Process Model (run)..."); // // // Write summary information on the option for this compilation. // writeSummary(" "); // writeSummary("Compilation:"); // writeSummary("\tDate :\t-"); // writeSummary("\tVersion :\t-"); // writeSummary("\tJAXB version :\t" + Options.getBuildID()); // writeSummary("\tInclude file :\t" + (includeFile == null ? "<none>" : includeFile)); // writeSummary("\tExclude file :\t" + (excludeFile == null ? "<none>" : excludeFile)); // writeSummary("\tSummary file :\t" + (summaryFile == null ? "<none>" : summaryFile)); // writeSummary("\tInstantiate :\t" + instantiation); // writeSummary("\tCollection :\t" + collectionClass); // writeSummary("\tInterface :\t" + interfaceClass); // writeSummary("\tDelete :\t" + deleteCandidates); // writeSummary(" "); // // // Find candidate classes for transformation. // // Candidates are classes having exactly one field which is a collection. // candidates = findCandidateClasses(model.getModel(), errorHandler); // // // Write information on candidate classes to summary file. // writeSummary("Candidates:"); // for (Candidate c : candidates.values()) // { // if (isIncluded(c)) // { // writeSummary("\t[+] " + getIncludeOrExcludeReason(c) + ":\t" + c.getClassName()); // candidateCount++; // } // else // writeSummary("\t[-]: " + getIncludeOrExcludeReason(c) + ":\t" + c.getClassName()); // } // writeSummary("\t" + candidateCount + " candidate(s) being considered."); // writeSummary(" "); // // // Visit all classes generated by JAXB. // writeSummary("Modifications:"); // for (ClassOutline classOutline : model.getClasses()) // { // // Get the implementation class for the current class. // implementationClass = classOutline.implClass; // // // Visit all fields in this class. // for (FieldOutline field : classOutline.getDeclaredFields()) // { // // // Extract the field name and type of the current field. // fieldName = field.getPropertyInfo().getName(false); // typeName = field.getRawType().fullName(); // // // Check to see if the current field references one of the candidate classes. // candidate = candidates.get(typeName); // // if (candidate != null && isIncluded(candidate)) // { // // We have a candidate field to be replaced with a wrapped version. Report finding to // // summary file. // writeSummary("\t" + classOutline.target.getName() + "#" + fieldName + "\t" + typeName); // modificationCount++; // // // Create the new interface and collection classes using the specified interface and // // collection classes (configuration) with an element type corresponding to // // the element type from the collection present in the candidate class (narrowing). // JDefinedClass candidateClass = model.getClazz(candidate.getClassInfo()).implClass; // List<JClass> itemNarrowing = ((JClass) candidateClass.fields().get( // candidate.getFieldName()).type()).getTypeParameters(); // JClass newInterfaceClass = implementationClass.owner().ref(interfaceClass).narrow( // itemNarrowing); // JClass newCollectionClass = implementationClass.owner().ref(collectionClass).narrow( // itemNarrowing); // // // Remove original field which refers to the inner class. // JFieldVar implField = implementationClass.fields().get(fieldName); // implementationClass.removeField(implField); // // // Add new wrapped version of the field using the original field name. // // CODE: protected I<T> fieldName; // implField = implementationClass.field(JMod.PROTECTED, newInterfaceClass, fieldName); // // // If instantiation is specified to be "early", add code for creating new instance of the // // collection class. // if (instantiation == Instantiation.EARLY) // { // writeDebug("Applying EARLY instantiation..."); // // CODE: ... fieldName = new C<T>(); // implField.init(JExpr._new(newCollectionClass)); // } // // // Annotate the new field with the @XmlElementWrapper annotation using the original field // // name as name. // JAnnotationUse annotation = implField.annotate(XmlElementWrapper.class); // annotation.param("name", ElementWrapperPlugin1.elementName(field.getPropertyInfo()) == null ? fieldName : ElementWrapperPlugin1.elementName(field.getPropertyInfo())); // writeDebug("XmlElementWrapper(name=" + (ElementWrapperPlugin1.elementName(field.getPropertyInfo()) == null ? fieldName : ElementWrapperPlugin1.elementName(field.getPropertyInfo())) + ")"); // // // Annotate the new field with the @XmlElement annotation using the field name from the // // wrapped type as name. // annotation = implField.annotate(XmlElement.class); // annotation.param("name", candidate.getWrappedSchemaTypeName() == null ? candidate.getFieldName() : candidate.getWrappedSchemaTypeName()); // writeDebug("XmlElement(name=" + (candidate.getWrappedSchemaTypeName() == null ? candidate.getFieldName() : candidate.getWrappedSchemaTypeName()) + ")"); // // // Find original getter and setter methods to remove. // methodsToRemove = new ArrayList<JMethod>(); // for (JMethod m : implementationClass.methods()) // if (m.name().equals("set" + firstUpper(fieldName)) // || m.name().equals("get" + firstUpper(fieldName))) methodsToRemove.add(m); // // // Remove original getter and setter methods. // for (JMethod m : methodsToRemove) // implementationClass.methods().remove(m); // // // Add a new getter method returning the (wrapped) field added. // // CODE: public I<T> getFieldname() { ... }; // JMethod method = implementationClass.method(JMod.PUBLIC, newInterfaceClass, "get" // + firstUpper(fieldName)); // // if (instantiation == Instantiation.LAZY) // { // writeDebug("Applying LAZY instantiation..."); // // CODE: if (fieldName == null) fieldName = new C<T>(); // method.body()._if(JExpr.ref(fieldName).eq(JExpr._null()))._then().assign( // JExpr.ref(fieldName), JExpr._new(newCollectionClass)); // } // // // CODE: return "fieldName"; // method.body()._return(JExpr.ref(fieldName)); // } // } // } // writeSummary("\t" + modificationCount + " modification(s) to original code."); // writeSummary(" "); // // writeSummary("Deletions:"); // if (deleteCandidates) // { // // // REMOVED: // // Get the default package from options. // // This code was used earlier to only get the factory class from the default package. // // pkg = model.getModel().codeModel._package(opt.defaultPackage); // // JDefinedClass factoryClass = pkg._getClass(factoryClassName); // // JPackage pkg; // // // Get the factory class from the default package. // JDefinedClass factoryClass; // JDefinedClass candidateClass; // // // Visit all candidate classes. // for (Candidate c : candidates.values()) // { // // Only consider candidates that are actually included... // if (isIncluded(c)) // { // // Get the defined class for candidate class. // candidateClass = model.getClazz(c.getClassInfo()).implClass; // // // ADDED: // // This code was added to locate the ObjectFactory inside the package of the candidate class. // pkg = candidateClass._package(); // factoryClass = pkg._getClass(factoryClassName); // // // Remove methods referencing the candidate class from the ObjectFactory. // methodsToRemove = new ArrayList<JMethod>(); // for (JMethod m : factoryClass.methods()) // if (m.type().compareTo(candidateClass) == 0) methodsToRemove.add(m); // // for (JMethod m : methodsToRemove) // { // writeSummary("\tRemoving method " + m.type().fullName() + " " + m.name() + " from " // + factoryClass.fullName()); // factoryClass.methods().remove(m); // deletionCount++; // } // // // Remove the candidate from the class or package it is defined in. // if (candidateClass.parentContainer().isClass()) // { // // The candidate class is an inner class. Remove the class from its parent class. // JDefinedClass parent = (JDefinedClass) candidateClass.parentContainer(); // writeSummary("\tRemoving class " + candidateClass.fullName() + " from class " // + parent.fullName()); // Iterator<JDefinedClass> itor = parent.classes(); // while (itor.hasNext()) // if (itor.next().equals(candidateClass)) // { // itor.remove(); // break; // } // deletionCount++; // } // else // { // // The candidate class in in a package. Remove the class from the package. // JPackage parent = (JPackage) candidateClass.parentContainer(); // writeSummary("\tRemoving class " + candidateClass.fullName() + " from package " // + parent.name()); // parent.remove(candidateClass); // deletionCount++; // } // } // } // } // writeSummary("\t" + deletionCount + " deletion(s) from original code."); // writeSummary(" "); // // try // { // writeDebug("Closing summary..."); // closeSummary(); // } // catch (IOException e) // { // // TODO BJH: How would this type of exception be reported? Should it just be ignored? // } // writeDebug("Done"); // return true; // } // // protected boolean isIncluded(Candidate candidate) // { // // // // A candidate is included if, ... // // 1. No includes and no excludes have been specified // // 2. Includes have been specified and canditate is included, and no excludes have been // // specified. // // 3. No includes have been specified and excludes have been specified and candidate is not in // // excludes. // // 4. Both includes and excludes have been specified and candidate is in includes and not in // // excludes. // // // if (!hasIncludes() && !hasExcludes()) // return true; // [+] (default) // else if (hasIncludes() && !hasExcludes()) // return include.contains(candidate.getClassName()); // [+/-] (included) // else if (!hasIncludes() && hasExcludes()) // return !exclude.contains(candidate.getClassName()); // [+/-] (excluded) // else // return include.contains(candidate.getClassName()) // && !exclude.contains(candidate.getClassName()); // [+/-] (override) // } // // protected String getIncludeOrExcludeReason(Candidate candidate) // { // if (!hasIncludes() && !hasExcludes()) // return "(default)"; // [+] (default) // else if (hasIncludes() && !hasExcludes()) // return "(included)"; // else if (!hasIncludes() && hasExcludes()) // return "(excluded)"; // else // return "(override)"; // } // // protected boolean hasIncludes() // { // return include != null; // } // // protected boolean hasExcludes() // { // return exclude != null; // } // // /** // * // * @param file // * @param candidates // * @throws IOException // */ // protected void readCandidates(File file, Set<String> candidates) throws IOException // { // LineNumberReader input; // String line; // // input = new LineNumberReader(new FileReader(file)); // while ((line = input.readLine()) != null) // { // line = line.trim(); // // // Lines starting with # are considered comments. // if (!line.startsWith("#")) candidates.add(line); // } // input.close(); // } // // /** // * // * @param s // * @return // */ // protected String firstUpper(String s) // { // if (s == null) return null; // if (s.length() == 0) return ""; // return s.substring(0, 1).toUpperCase() + s.substring(1); // } // // /** // * // * @param model // * @param errorHandler // * @return // */ // protected Map<String, Candidate> findCandidateClasses(Model model, ErrorHandler errorHandler) // { // Map<String, Candidate> candidates = new HashMap<String, Candidate>(); // // // Visit all beans created by JAXB processing. // for (CClassInfo classInfo : model.beans().values()) // { // String className = classInfo.fullName(); // // // The candidate class must have exactly one property. // if (classInfo.getProperties().size() == 1) // { // CPropertyInfo property = classInfo.getProperties().get(0); // // // The property must be a collection // if (property.isCollection()) // { // if (property.ref().size() == 1) // { // // We have a candidate class. // Candidate candidate = new Candidate(classInfo); // candidates.put(className, candidate); // writeDebug("Candidate found: " + candidate.getClassName() + ", " + candidate.getFieldName() + ", [" + candidate.getFieldTypeName() + "]"); // } // } // } // } // return candidates; // } // // protected void writeSummary(String s) // { // if (summary != null) // { // summary.println(s); // if (verbose) System.out.println(s); // } // else if (verbose) System.out.println(s); // } // // protected void closeSummary() throws IOException // { // if (summary != null) summary.close(); // } // // protected void writeDebug(String s) // { // if (debugMode) System.out.println("DEBUG:" + s); // } // // protected static String elementName(CPropertyInfo property) // { // try // { // if (property instanceof CElementPropertyInfo) // { // return ((CElementPropertyInfo) property).getTypes().get(0).getTagName().getLocalPart(); // } // else // return null; // } // catch (Exception ex) // { // return null; // } // } // // enum Instantiation // { // EARLY, LAZY // } // // /** // * // * @author bjh // * // */ // class Candidate // { // protected CClassInfo classInfo; // protected CPropertyInfo propertyInfo; // protected CTypeInfo propertyTypeInfo; // // protected JDefinedClass implClass; // protected JFieldVar field; // protected String wrappedSchemaTypeName = null; // // public Candidate(CClassInfo classInfo) // { // this.classInfo = classInfo; // this.propertyInfo = classInfo.getProperties().get(0); // this.propertyTypeInfo = propertyInfo.ref().iterator().next(); // this.wrappedSchemaTypeName = ElementWrapperPlugin1.elementName(propertyInfo); // } // // public CClassInfo getClassInfo() // { // return classInfo; // } // // public CPropertyInfo getPropertyInfo() // { // return propertyInfo; // } // // public CTypeInfo getPropertyTypeInfo() // { // return propertyTypeInfo; // } // // public String getClassName() // { // return classInfo.fullName(); // } // // public String getFieldName() // { // return getPropertyInfo().getName(false); // } // // public String getFieldTypeName() // { // return propertyTypeInfo.getType().fullName(); // } // // public String getWrappedSchemaTypeName() // { // return wrappedSchemaTypeName; // } // } // // public static void main(String[] args) // { // // } //}