/** * Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET * (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije * informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE * COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp., * INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM * ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC)) * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.societies.maven; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; /** * @phase process-sources * @goal convert */ public class Jaxb2Simple extends AbstractMojo { private final String FOLDER_PATH = "src/main/java"; //"target/generated-sources/xjc/" private final String TO_STRING_CODE = " }\n\n @Override\n public String toString() {\n return this.value();\n }\n}\n"; /** * Output directory for schemas * * @parameter default-value="src/main/resources/" */ private String folderOutputDirectory; /** * Input directory for schemas * * @parameter default-value="${project.build.directory}/generated-sources/" */ private String folderInputDirectory = FOLDER_PATH; /** * To wrap all Societies schemas with the Android Parcelable Interface * * @parameter default-value=false */ private boolean wrapIntoParcelable; private Map<String, Set<String>> newClassesOnPackage = new HashMap<String, Set<String>>(); private Map<String, String> namespaceForPackage = new HashMap<String, String>(); public void execute() throws MojoExecutionException { // Init initParameters(); File startingDirectory= new File(folderInputDirectory); getLog().info("Source Directory: " + folderInputDirectory); List<File> files = null; try { files = FileListing.getFileListing(startingDirectory); // First process ObjectFactories and package-infos: will potentially create new files for (File javaFile : files) { if (javaFile.isFile() && javaFile.getName().equals("ObjectFactory.java")) { getLog().debug("Processing: " + javaFile.getAbsolutePath()); processObjectFactory(javaFile); } if (javaFile.isFile() && javaFile.getName().equals("package-info.java")) { getLog().debug("Processing: " + javaFile.getAbsolutePath()); processPackageInfo(javaFile); } } // Reload files files = FileListing.getFileListing(startingDirectory); // Process all java files now and delete unwanted ones for (File javaFile : files) { if (javaFile.isFile()) { //IGNORE DIRECTORIES if (javaFile.getName().equals("ObjectFactory.java") || javaFile.getName().equals("package-info.java") || javaFile.getName().equals("Adapter2.java")) { getLog().debug("Deleting: " + javaFile.getAbsolutePath()); javaFile.delete(); } else { if (javaFile.getName().endsWith(".java")) { getLog().debug("Processing: " + javaFile.getAbsolutePath()); String newSchemaContent = processCodeFile(javaFile); FileWriter newFile = new FileWriter(javaFile.getAbsolutePath()); newFile.write(newSchemaContent); newFile.close(); } } } } } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private String processCodeFile(File javaFile) throws FileNotFoundException { Scanner scanner = null; String newSchemaContent = new String(); // READ THE ORIGINAL .java FILE scanner = new Scanner(javaFile); StringBuffer schemaContent = new StringBuffer(); while (scanner.hasNextLine()) { schemaContent.append(scanner.nextLine()+"\n"); } // Main Annotations Replacement newSchemaContent = findReplacePatterns(schemaContent); // Empty Elements Processing Matcher m = packagePattern.matcher(newSchemaContent); m.find(); String pkgName = m.group(1); Map<String,String> fieldClasses = detectFields(newSchemaContent, newClassesOnPackage.get(pkgName)); for (String fieldName : fieldClasses.keySet()) { String className = fieldClasses.get(fieldName); getLog().debug("Changing class of field '"+fieldName+"' to class '"+className+"'"); newSchemaContent = replaceFieldAndAccessors(newSchemaContent, fieldName, className); } //ENUM NEEDS TO BE SERIALIZED WITH "VALUE", NOT "NAME" if (newSchemaContent.indexOf("public enum ") > 0) { String textToFind = ".*}\n\n}\n"; String textToReplace = TO_STRING_CODE; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); } //ADD IMPORT ElementList if (newSchemaContent.indexOf("@ElementList") > 0) { String textToFind = "(import org.simpleframework.xml.Element;)"; String textToReplace = "$1\nimport org.simpleframework.xml.ElementList;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); } // Parcelable Stuff if (wrapIntoParcelable) { newSchemaContent = replaceParcelableStuff(javaFile, newSchemaContent); } newSchemaContent = createEqualsMethod(javaFile, newSchemaContent); return newSchemaContent; } private static String replaceFieldAndAccessors(String newSchemaContent, String fieldName, String className) { String textToFind = "protected String "+fieldName+";\n"; String textToReplace = "protected "+className+" "+fieldName+";\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); String capitalizedfieldName = Character.toUpperCase(fieldName.charAt(0))+fieldName.substring(1);; textToFind = "public String get"+capitalizedfieldName+"\\(\\) \\{\n"; textToReplace = "public "+className+" get"+capitalizedfieldName+"() {\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); textToFind = "public void set"+capitalizedfieldName+"\\(String value\\) \\{\n"; textToReplace = "public void set"+capitalizedfieldName+"("+className+" value) {\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); return newSchemaContent; } private static final Pattern packagePattern = Pattern.compile("package ([\\d\\w.-]*);"); private static final Pattern fieldPattern = Pattern.compile("\\s*protected String (\\w*);\\s*"); private Map<String,String> detectFields(String newSchemaContent, Set<String> newClasses) { Map<String,String> fieldClasses = new HashMap<String, String>(); Matcher matcher = fieldPattern.matcher(newSchemaContent); while (matcher.find()) { String fieldName = matcher.group(1); for (String cl : newClasses) { if (cl.equalsIgnoreCase(fieldName)) { fieldClasses.put(fieldName,cl); //System.out.println("replace 'protected String "+fieldName+";' with 'protected "+cl+" "+fieldName+";'"); break; } } } return fieldClasses; } private String findReplacePatterns(StringBuffer schemaContent) { String newSchemaContent; String textToFind; String textToReplace; newSchemaContent = schemaContent.toString(); //import javax.xml.bind.annotation.* -> import org.simpleframework.xml.* //textToFind = "import javax.xml.bind.annotation.*import javax.xml.bind.annotation.\\w*;"; //textToReplace = "import org.simpleframework.xml.*;"; //newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace, Pattern.DOTALL|Pattern.CASE_INSENSITIVE); //import javax\.xml\.bind\.annotation\.XmlAccessType/import org.simpleframework.xml.DefaultType textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlAccessType;"; textToReplace = "import org.simpleframework.xml.DefaultType;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlAccessorType/import org.simpleframework.xml.Default/ textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlAccessorType;\n"; //textToReplace = "import org.simpleframework.xml.Default;"; textToReplace = ""; //PubSub has a class called Default also! Need to refer to xml.default by FQ name newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlAttribute;/import org.simpleframework.xml.Attribute; textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlAttribute;"; textToReplace = "import org.simpleframework.xml.Attribute;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlElement;/import org.simpleframework.xml.Element;/ textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlElement;"; textToReplace = "import org.simpleframework.xml.Element;\nimport org.simpleframework.xml.Namespace;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlType;/import org.simpleframework.xml.Element;\nimport org.simpleframework.xml.Order;/ textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlType;"; textToReplace = "import org.simpleframework.xml.Order;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlRootElement/import org.simpleframework.xml.Root/ textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlRootElement;"; textToReplace = "import org.simpleframework.xml.Root;\nimport org.simpleframework.xml.Namespace;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlValue/import org.simpleframework.xml.Text textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlValue;"; textToReplace = "import org.simpleframework.xml.Text;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlElements/import org.simpleframework.xml.ElementList textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlElements;"; textToReplace = "import org.simpleframework.xml.ElementList;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter -> import org.simpleframework.xml.convert.Convert; textToFind = "import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;"; textToReplace = "import org.simpleframework.xml.convert.Convert;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import org.w3._2001.xmlschema.Adapter1; -> import org.societies.simple.converters.URIConverter; textToFind = "import org.w3._2001.xmlschema.Adapter1;"; textToReplace = "import org.societies.simple.basic.URIConverter;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import org.w3._2001.xmlschema.Adapter1; -> import org.societies.simple.converters.URIConverter; textToFind = "import org.w3._2001.xmlschema.Adapter2;"; textToReplace = "import org.societies.simple.basic.DateConverter;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -> import org.societies.simple.converters.CollapsedStringAdapter; textToFind = "import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;"; textToReplace = "import org.societies.simple.basic.CollapsedStringAdapter;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlJavaTypeAdapter(Adapter1 .class) -> @Convert(URIConverter.class) textToFind = "@XmlJavaTypeAdapter\\(Adapter1.*\\.class?\\)"; textToReplace = "@Convert(URIConverter.class)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlJavaTypeAdapter(Adapter1 .class) -> @Convert(URIConverter.class) textToFind = "@XmlJavaTypeAdapter\\(Adapter2.*\\.class?\\)"; textToReplace = "@Convert(DateConverter.class)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); textToFind = "import java.util.Date;"; textToReplace = "import java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlJavaTypeAdapter(CollapsedStringAdapter.class) -> @Convert(CollapsedStringAdapter.class) textToFind = "@XmlJavaTypeAdapter\\(CollapsedStringAdapter.class?\\)"; textToReplace = "@Convert(CollapsedStringAdapter.class)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //REMOVE namespace FROM XmlElement ANNOTATION @XmlElement(namespace = "jabber:x:data") //s/\(@XmlElement(name = ".*"\), namespace\( = ".*"\))/\1, required = false)\n @Namespace(reference\2)/ textToFind = "(@XmlElement\\(.*)namespace( = \".*\")\\)"; textToReplace = "$1required = false)\n @Namespace(reference$2)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlElement(name = "Activity", namespace = "http://societies.org/api/schema/activity", required = true) textToFind = "(@XmlElement\\(.*)namespace( = \".*\"),(.*)\\)"; textToReplace = "$1$3)\n @Namespace(reference$2)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); // @XmlElement with List -> @XmlElementList @XmlElement(nillable = true) -> @ElementList(inline=true, entry="Service") // @XmlElement(name[ ]*=\(.*\)).*\(\n.*List\<.*\>.*;\)/@ElementList(inline=true, entry=\1)\2/ textToFind = "@XmlElement\\(.*?\\)(\n.*?List\\<(.*?)\\>.*?;)"; //textToReplace = "@ElementList(inline=true, entry=\"$2\")$1"; textToReplace = "$1"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace, Pattern.DOTALL|Pattern.CASE_INSENSITIVE); //@XmlElement -> @Element //1) if "required = true|false" is missing then add "required=false" else do nothing //2) remove nillable=true|false //@XmlElement(required = true, type = Integer.class, nillable = true) //textToFind = "(@XmlElement\\(.*)nillable = true|false\\)"; textToFind = ", nillable = (true|false)"; textToReplace = ""; //"$1)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlElement(required = true, type = Integer.class, nillable = true) textToFind = "@XmlElement\\(nillable = true\\)"; textToReplace = "@Element(required=false)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlElement(\(.*required.*\))/@Element(\1)/ @XmlElement(required = true) //textToFind = "@XmlElement(\\(.*required.*\\))"; textToFind = "@XmlElement\\((.*required.*?)\\)"; textToReplace = "@Element($1)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlElement(\(.*\))/@Element(required=false,\1)/ textToFind = "@XmlElement\\((.*?)\\)"; textToReplace = "@Element($1, required=false)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //NAMESPACE Pattern patternNS = Pattern.compile("package (.*);", Pattern.DOTALL|Pattern.CASE_INSENSITIVE); Matcher matcherNS = patternNS.matcher(newSchemaContent); String ns = ""; if (matcherNS.find()) { String pkgTmp = matcherNS.group(); String pkgFinal = pkgTmp.substring(8, pkgTmp.indexOf(";")); // String[] nsArr = pkgFinal.split("\\."); // ns = "@Namespace(reference=\"http://" + nsArr[1] + "." + nsArr[0]; // for(int i=2; i<nsArr.length; i++) // ns+="/" + nsArr[i]; // ns += "\")\n"; ns = "@Namespace(reference=\""+namespaceForPackage.get(pkgFinal)+"\")\n"; // fix for non-default namespaces (eg pubsub#event) issue } // @XmlRootElement -> @Root + @Namespace(reference="http://...) // s/@XmlRootElement(\(.*\))/@Root(\1, strict=false)/ //textToFind = "@XmlRootElement(\\(.*)\\)\n"; textToFind = "@XmlRootElement(\\(.*?)\\)\n"; textToReplace = "@Root$1, strict=false)\n" + ns; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlType(.*propOrder[ ]*\(=.*\)/@Order(elements\1/ // textToFind = "@XmlType\\(.*propOrder"; // textToReplace = "@Order(elements"; // newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); // TODO discarding element order information instead of placing @Order annotations textToFind = "@XmlType\\([^\\)]*\\)"; textToReplace = ""; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); // @XmlAccessorType([ ]*XmlAccessType\.\(.*\))\n@XmlType(\(.*\)[ ]*,[ ]*propOrder[ ]*\(=.*\)/@Default(DefaultType.\1)\n@Order(elements\3/ textToFind = "@XmlAccessorType\\(XmlAccessType.FIELD\\)"; textToReplace = "@org.simpleframework.xml.Default(value=DefaultType.FIELD, required=false)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); // @XmlAccessorType([ ]*XmlAccessType\.\(.*\))\n@XmlType(\(.*\))/@Default(DefaultType.\1)\n@Root(\2, strict=false //Pattern patternAccessor1 = Pattern.compile("@XmlAccessorType([ ]*XmlAccessType\\.\\(.*\\))\\n@XmlType(\\(.*\\))", Pattern.DOTALL|Pattern.CASE_INSENSITIVE); //Matcher matcherAccessor1 = patternAccessor1.matcher(newSchemaContent); //newSchemaContent = matcherAccessor1.replaceAll("@Default(DefaultType.$1)\n@Root($2, strict=false"); // @XmlAccessorType([ ]*XmlAccessType\.\(.*\))\n@XmlType(\(.*\)[ ]*,[ ]*propOrder[ ]*\(=.*\)/@Default(DefaultType.\1)\n@Order(elements\3/ //Pattern patternAccessor2 = Pattern.compile("@XmlAccessorType([ ]*XmlAccessType\\.\\(.*\\))\\n@XmlType(\\(.*\\)[ ]*,[ ]*propOrder[ ]*\\(=.*\\)", Pattern.DOTALL|Pattern.CASE_INSENSITIVE); //Matcher matcherAccessor2 = patternAccessor2.matcher(newSchemaContent); //newSchemaContent = matcherAccessor.replaceAll("@Default(DefaultType.$1)\n@Order(elements$3"); // @XmlAttribute -> @Attribute //if "required = true|false" is missing then add "required=false" else do nothing textToFind = "@XmlAttribute\\((.*, required = true|false)\\)"; textToReplace = "@Attribute($1)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //ADD required=false IF MISSING textToFind = "@XmlAttribute\\((.*?(?!required = true|false))\\)"; textToReplace = "@Attribute($1, required=false)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlAttribute/@Attribute(required=false)/ textToFind = "@XmlAttribute\n"; textToReplace = "@Attribute(required=false)\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlValue -> @Text textToFind = "@XmlValue"; textToReplace = "@Text(required=false)"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //REMOVE @XmlSchemaType(name = "anyURI") textToFind = "@XmlSchemaType\\(name = \".*\"\\)\n "; textToReplace = ""; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //ENUMERATOR FILE - REMOVE ALL ANNOTATIONS textToFind = "@XmlEnum.*?\n"; textToReplace = ""; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlType(name = "methodType") textToFind = "@XmlType\\(name = \".*?\"\\)?\n"; textToReplace = ""; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //@XmlSeeAlso/,/}) textToFind = "@XmlSeeAlso.*?}\\)\n"; textToReplace = ""; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace, Pattern.DOTALL|Pattern.CASE_INSENSITIVE); // @XmlAnyElement.* textToFind = "@XmlAnyElement.*?\n"; textToReplace = ""; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlAnyElement;/d textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlAnyElement;"; textToReplace = "\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlAnyAttribute;/d textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlAnyAttribute;"; textToReplace = "\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlSeeAlso;/d textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlSeeAlso;"; textToReplace = "\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlSchemaType;/d textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlSchemaType;"; textToReplace = "\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlEnum;/d textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlEnum;"; textToReplace = "\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //import javax\.xml\.bind\.annotation\.XmlEnumValue;/d textToFind = "import javax\\.xml\\.bind\\.annotation\\.XmlEnumValue;"; textToReplace = "\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); //COMPLETELY REMOVE @Element(defaultValue = "", required=false) textToFind = "@Element\\(defaultValue = \".*\", required=false\\)"; textToReplace = ""; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); // /@XmlSchemaType.*/d // /@XmlAnyAttribute.*/d return newSchemaContent; } private String createEqualsMethod(File javaFile, String schemaContent) { String textToFind; String textToReplace; // -- Check if this file has to be Parcelable if (isPatternMatching("Adapter1", javaFile.getAbsolutePath())) { return schemaContent; } if (isPatternMatching("Adapter2", javaFile.getAbsolutePath())) { return schemaContent; } if (!isPatternMatching("xjc", javaFile.getAbsolutePath())) { return schemaContent; } // -- Collect information about the file // Retrieve ClassName (even if it is an enum) Pattern patternClassName = Pattern.compile("public (?:abstract )?(class|enum) (.+)( |\\s)"); Matcher matcherClassName = patternClassName.matcher(schemaContent); // Not a class or an enum: stop everything if (!matcherClassName.find()) { return schemaContent; } String className = matcherClassName.group(2).trim(); className = className.replace(" {", ""); // For enum and empty class it is useful getLog().debug("###ClassName:"+className); // Is it an enum? boolean isEnum = "enum".equals(matcherClassName.group(1).trim()); // Is abstract? boolean isAbstract = isPatternMatching(" abstract ", schemaContent); // Is it extending something? boolean isExtension = isPatternMatching("extends ", schemaContent); // Is it requiring a default constructor? boolean requiredDefaultConstructor = !isPatternMatching("public "+className+"\\(", schemaContent); // Retrieve all Fields information LinkedHashMap <String, String> fields = new LinkedHashMap <String, String>(); Pattern patternFields = Pattern.compile("(?:protected|private) (?:final )?(?:static )?([^ ]+) ([^ ]+);\n", Pattern.CASE_INSENSITIVE); Matcher matcherFields = patternFields.matcher(schemaContent); while (matcherFields.find()) { // In case the name is overrided Pattern patternOverrideField = Pattern.compile("@Element\\(name = \"("+matcherFields.group(2)+")\",? ?.*? ?\\)", Pattern.CASE_INSENSITIVE); Matcher matcherOverrideField = patternOverrideField.matcher(schemaContent); if (matcherOverrideField.find()) { fields.put(matcherOverrideField.group(1), matcherFields.group(1)); getLog().debug("#Attr:"+matcherFields.group(1)+" "+matcherOverrideField.group(1)); } // Not overrided, use the found one else { fields.put(matcherFields.group(2), matcherFields.group(1)); getLog().debug("#Attr:"+matcherFields.group(1)+" "+matcherFields.group(2)); } } String newSchemaContent = new String(schemaContent); if (!isEnum && !isAbstract) { // Equals StringBuilder equalsStuff = new StringBuilder("\t/**\n\t * This method is not tested, and using contains on this object may failed\n\t */\n\tpublic boolean equals(Object o) {\n"); equalsStuff.append("\t\tif (o == null) { return false; }\n"); equalsStuff.append("\t\tif (o == this) { return true; }\n"); equalsStuff.append("\t\tif (o.getClass() != getClass()) {\n"); equalsStuff.append("\t\t\treturn false;\n"); equalsStuff.append("\t\t}\n"); // No fields if (fields.size() <= 0) { equalsStuff.append("\t\treturn true;\n"); } else { equalsStuff.append("\t\t"+className+" rhs = ("+className+") o;\n"); equalsStuff.append("\t\treturn (\n"); // Super equals if (isExtension) { equalsStuff.append("\t\t\tsuper.equals(rhs)\n"); } // Equals for all fields int i = 0; for (String fieldName : fields.keySet()) { String type = fields.get(fieldName); String fieldNameUcfirst = fieldName.replaceFirst("[a-zA-Z]{1}", fieldName.substring(0,1).toUpperCase()); equalsStuff.append("\t\t\t"); // Not first if (isExtension || 0 != i) { equalsStuff.append("&& "); } String accessor = "get"+fieldNameUcfirst+"()"; if (isBooleanType(type)) { accessor = "is"+fieldNameUcfirst+"()"; } // Simple type if (isSimpleType(type)) { equalsStuff.append("(this."+accessor+" == rhs."+accessor+")"); } // Object type else { equalsStuff.append("("); equalsStuff.append("this."+accessor+" == rhs."+accessor); // same reference equalsStuff.append("|| (null != this."+accessor+" && this."+accessor+".equals(rhs."+accessor+"))"); // or same content equalsStuff.append(")"); } // else if (!isListType(type)) { // } // // List type // else { // } equalsStuff.append("\n"); i++; } equalsStuff.append("\t\t);\n"); } equalsStuff.append("\t}\n\n"); // - HashCode StringBuilder hashCodeStuff = new StringBuilder("\t/**\n\t * This method is not tested, and using contains on this object may failed\n\t */\n\tpublic int hashCode() {\n"); hashCodeStuff.append("\t\tint result = 7;\n"); hashCodeStuff.append("\t\tfinal int multiplier = 31;\n"); // No fields if (!isExtension && fields.size() <= 0) { hashCodeStuff.append("\t\treturn result*multiplier;\n"); } else { // Super equals if (isExtension) { hashCodeStuff.append("\t\tresult = multiplier*result + super.hashCode();\n"); } // Equals for all fields int i = 0; for (String fieldName : fields.keySet()) { String type = fields.get(fieldName); String fieldNameUcfirst = fieldName.replaceFirst("[a-zA-Z]{1}", fieldName.substring(0,1).toUpperCase()); hashCodeStuff.append("\t\t"); String accessor = "get"+fieldNameUcfirst+"()"; if (isBooleanType(type)) { accessor = "is"+fieldNameUcfirst+"()"; } // Simple type if (isSimpleType(type)) { if (isBooleanType(type)) { hashCodeStuff.append("result = multiplier*result + (this."+accessor+" ? 1231 : 1237);\n"); } else if ("long".equals(type)) { hashCodeStuff.append("result = multiplier*result + (int)(this."+accessor+" ^(this."+accessor+" >>> 32));\n"); } else { hashCodeStuff.append("result = multiplier*result + (int)this."+accessor+";\n"); } } // Object type else { hashCodeStuff.append("result = multiplier*result + (null == this."+accessor+" ? 0 : this."+accessor+".hashCode());\n"); } i++; } hashCodeStuff.append("\t\treturn result;\n"); } hashCodeStuff.append("\t}\n\n"); // - ToString StringBuilder toStringStuff = new StringBuilder("\tpublic String toString() {\n"); toStringStuff.append("\t\tfinal String separator = System.getProperty(\"line.separator\");\n"); toStringStuff.append("\t\tStringBuilder sb = new StringBuilder(\""+className+"(\"+separator);\n"); if (isExtension || fields.size() > 0) { // Super if (isExtension) { toStringStuff.append("\t\tsb.append(super.toString());\n"); } // Actual fields int i = 0; for (String fieldName : fields.keySet()) { String type = fields.get(fieldName); String fieldNameUcfirst = fieldName.replaceFirst("[a-zA-Z]{1}", fieldName.substring(0,1).toUpperCase()); toStringStuff.append("\t\t"); String accessor = "get"+fieldNameUcfirst+"()"; if (isBooleanType(type)) { accessor = "is"+fieldNameUcfirst+"()"; } // Simple type if (isSimpleType(type)) { if (isBooleanType(type)) { toStringStuff.append("sb.append(\""+fieldNameUcfirst+": \"+(this."+accessor+" ? \"yes\" : \"no\"));\n"); } else { toStringStuff.append("sb.append(\""+fieldNameUcfirst+": \"+this."+accessor+");\n"); } } // Object type else { toStringStuff.append("sb.append(\""+fieldNameUcfirst+": \"+this."+accessor+");\n"); } // Not the end if ((i+1) != fields.size()) { toStringStuff.append("\t\tsb.append(\",\"+separator);\n"); } i++; } } toStringStuff.append("\t\tsb.append(\")\"+separator);\n"); toStringStuff.append("\t\treturn sb.toString();\n"); toStringStuff.append("\t}\n\n"); textToFind = "}\n$"; textToReplace = "\n"+equalsStuff.toString()+hashCodeStuff.toString()+toStringStuff.toString()+"\n}\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); } return newSchemaContent; } private boolean isListType(String type) { return (!isSimpleType(type) && isListOrArray(type)); } private boolean isSimpleType(String type) { return ("int".equals(type) || "double".equals(type) || "boolean".equals(type) || "byte".equals(type) || "float".equals(type) || "long".equals(type) ); } private boolean isBooleanType(String type) { return ("boolean".equals(type) || "Boolean".equals(type)); } private String replaceParcelableStuff(File javaFile, String schemaContent) { String textToFind; String textToReplace; // -- Check if this file has to be Parcelable if (isPatternMatching("Adapter1", javaFile.getAbsolutePath())) { return schemaContent; } if (isPatternMatching("Adapter2", javaFile.getAbsolutePath())) { return schemaContent; } if (!isPatternMatching("xjc", javaFile.getAbsolutePath())) { return schemaContent; } // -- Collect information about the file // Retrieve ClassName (even if it is an enum) Pattern patternClassName = Pattern.compile("public (?:abstract )?(class|enum) (.+)( |\\s)"); Matcher matcherClassName = patternClassName.matcher(schemaContent); // Not a class or an enum: stop everything if (!matcherClassName.find()) { return schemaContent; } String className = matcherClassName.group(2).trim(); className = className.replace(" {", ""); // For enum and empty class it is useful getLog().debug("###ClassName:"+className); // Is it an enum? boolean isEnum = "enum".equals(matcherClassName.group(1).trim()); // Is abstract? boolean isAbstract = isPatternMatching(" abstract ", schemaContent); // Is it extending something? boolean isExtension = isPatternMatching("extends ", schemaContent); // Is it requiring a default constructor? boolean requiredDefaultConstructor = !isPatternMatching("public "+className+"\\(", schemaContent); // Retrieve all Fields information LinkedHashMap <String, String> fields = new LinkedHashMap <String, String>(); Pattern patternFields = Pattern.compile("(?:protected|private) (?:final )?(?:static )?([^ ]+) ([^ ]+);\n", Pattern.CASE_INSENSITIVE); Matcher matcherFields = patternFields.matcher(schemaContent); while (matcherFields.find()) { fields.put(matcherFields.group(2), matcherFields.group(1)); getLog().debug("#Attr:"+matcherFields.group(1)+" "+matcherFields.group(2)); } // -- Add Parcelable information to the file // - Implement parcelable Pattern patternIsSerializable = Pattern.compile("implements Serializable"); Matcher matcherIsSerializable = patternIsSerializable.matcher(schemaContent); boolean isSerializable = matcherIsSerializable.find(); // enum if (isEnum) { textToFind = "public enum (.+) "; textToReplace = "public enum $1 implements Parcelable "; } // Class else if (!isSerializable) { textToFind = "public class (.+) "; textToReplace = "public class $1 implements Parcelable "; } else { textToFind = "implements Serializable"; textToReplace = "implements Serializable, Parcelable"; } String newSchemaContent = findReplacePattern(schemaContent, textToFind, textToReplace); // - Add imports // Parcelable imports textToFind = "package (.+);"; textToReplace = "package $1;\n\n\nimport android\\.os\\.Parcel;\nimport android\\.os\\.Parcelable;\nimport java\\.util\\.Arrays;"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); // Specific imports (if some specific classes are found in the class) if (isPatternMatching("URI", newSchemaContent)) { textToFind = "package (.+);"; textToReplace = "package $1;\n\n\nimport java\\.net\\.URI;\nimport java\\.net\\.URISyntaxException;\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); } if (isPatternMatching("XMLGregorianCalendar", newSchemaContent)) { textToFind = "package (.+);"; textToReplace = "package $1;\n\n\nimport javax\\.xml\\.datatype\\.DatatypeConfigurationException;\nimport javax\\.xml\\.datatype\\.DatatypeFactory;\nimport javax\\.xml\\.datatype\\.XMLGregorianCalendar;\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); } if (isPatternMatching(" Object ", newSchemaContent)) { textToFind = "([\\(| ])Object "; textToReplace = "$1Parcelable "; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); } // -- Generate the parcelable inherited methods String parcelableStuff = generateParcelableStuff(isEnum, isExtension, isAbstract, requiredDefaultConstructor, className, fields); textToFind = "}\n$"; textToReplace = "\n"+parcelableStuff+"\n}\n"; newSchemaContent = findReplacePattern(newSchemaContent, textToFind, textToReplace); return newSchemaContent; } /** * Generate parcelable inherited methods * @param schemaContent * @param className * @param fieldClasses * @return */ private String generateParcelableStuff(boolean isEnum, boolean isExtension, boolean isAbstract, boolean requiredDefaultConstructor, String className, LinkedHashMap <String, String> fieldClasses) { StringBuilder str = new StringBuilder(); // Constructors if (requiredDefaultConstructor && !isEnum) { str.append("\tpublic PARCELABLECLASSNAME() { }\n\n"); } if (!isEnum || (isEnum && fieldClasses.size() > 0)) { str.append("\t"+(isEnum ? "" : "public ")+"PARCELABLECLASSNAME(Parcel in) {\n"); // Call to super constructor: already done in read // if (isExtension) { // str.append("\t\tsuper(in);\n"); // } if (isEnum) { str.append("READPARCELABLE"); } else { str.append("\t\treadFromParcel(in);\n"); } str.append("\t}\n\n"); } str.append("\tpublic int describeContents() {\n"); str.append("\t\treturn 0;\n"); str.append("\t}\n\n"); if (!isEnum) { str.append("\tprotected void readFromParcel(Parcel in) {\n"); if (isExtension) { str.append("\t\tsuper.readFromParcel(in);\n"); } str.append("READPARCELABLE"); str.append("\t}\n\n"); } str.append("\tpublic void writeToParcel(Parcel dest, int flags) {\n"); if (isExtension) { str.append("\t\tsuper.writeToParcel(dest, flags);\n"); } str.append("WRITEPARCELABLE"); str.append("\t}\n\n"); if (!isAbstract) { str.append("\tpublic static final Parcelable.Creator<PARCELABLECLASSNAME> CREATOR = new Parcelable.Creator<PARCELABLECLASSNAME>() {\n"); if (isEnum) { str.append("\t\tpublic PARCELABLECLASSNAME createFromParcel(final Parcel in) {\n"); str.append("\t\t\treturn PARCELABLECLASSNAME.fromValue(in.readString());\n"); str.append("\t\t}\n"); } else { str.append("\t\tpublic PARCELABLECLASSNAME createFromParcel(Parcel in) {\n"); str.append("\t\t\treturn new PARCELABLECLASSNAME(in);\n"); str.append("\t\t}\n"); } str.append("\t\tpublic PARCELABLECLASSNAME[] newArray(int size) {\n"); str.append("\t\t\treturn new PARCELABLECLASSNAME[size];\n"); str.append("\t\t}\n"); str.append("\t};\n\n"); } else { str.append("\t\tpublic static Parcelable.Creator CREATOR;\n"); } String parcelableStuff = str.toString(); // ClassName Pattern patternClassName = Pattern.compile("PARCELABLECLASSNAME"); Matcher matcherClassName = patternClassName.matcher(parcelableStuff); parcelableStuff = matcherClassName.replaceAll(className); // Write/Read Parcel StringBuilder strWrite = new StringBuilder(); StringBuilder strRead = new StringBuilder(); for (String fieldName : fieldClasses.keySet()) { String type = fieldClasses.get(fieldName); String writedMethod = "dest.write"+type2ParcelableAction(type); strWrite.append("\t\t"+type2ParcelableWriteData(type, fieldName, writedMethod)+";\n"); String readMethod = "in.read"+type2ParcelableAction(type); strRead.append("\t\t"+type2ParcelableReadData(type, fieldName, readMethod, className)+";\n"); } Pattern patternWrite = Pattern.compile("WRITEPARCELABLE"); Matcher matcherWrite = patternWrite.matcher(parcelableStuff); parcelableStuff = matcherWrite.replaceAll(strWrite.toString()); Pattern patternRead = Pattern.compile("READPARCELABLE"); Matcher matcherRead = patternRead.matcher(parcelableStuff); parcelableStuff = matcherRead.replaceAll(strRead.toString()); return parcelableStuff; } private String type2ParcelableWriteData(String type, String fieldName, String writedMethod) { if ("boolean".equals(type) || "Boolean".equals(type)) { return writedMethod+"("+fieldName+" ? 1 : 0)"; } String globalType = type2ParcelableAction(type); if ("Parcelable".equals(globalType)) { return writedMethod+"("+fieldName+", flags)"; } if (isListOrArray(type)) { if (globalType.startsWith("Parcelable") && globalType.endsWith("List")) { // writedMethod = writedMethod.replace("List", "Array"); // return writedMethod+"(("+typeToParcelableRawType(type, false)+"[]) "+fieldName+".toArray(), flags)"; return "dest.writeTypedList("+fieldName+")"; } if ("Int".equals(typeToParcelableRawType(type, false)) && globalType.endsWith("List")) { return "dest.writeList("+fieldName+")"; } if ("URI".equals(typeToParcelableRawType(type, false)) && globalType.endsWith("List")) { StringBuilder strList = new StringBuilder("List<String> "+fieldName+"StringList = new ArrayList<String>();\n"); strList.append("\t\tfor(int i=0; i<"+fieldName+".size(); i++) {\n"); strList.append("\t\t\t"+fieldName+"StringList.add("+fieldName+".get(i).toASCIIString());\n"); strList.append("\t\t}\n"); strList.append("\t\tdest.writeStringList("+fieldName+"StringList)"); return strList.toString(); } if ("Byte".equals(typeToParcelableRawType(type, false)) ) { String sByteCode = "dest.writeInt(" + fieldName + ".length);\n\t\t" + "dest.writeByteArray(" + fieldName + ")"; return sByteCode; } return writedMethod+"("+fieldName+")"; } if ("URI".equals(typeToParcelableRawType(type, false))) { return "dest.writeString("+fieldName+".toASCIIString())"; } if ("XMLGregorianCalendar".equals(typeToParcelableRawType(type, false))) { return "dest.writeString("+fieldName+".toString())"; } if ("Date".equals(typeToParcelableRawType(type, false))) { return "DateFormat df = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss Z\");\n\t\tString val = df.format(" +fieldName+ ");\n\t\tdest.writeString(val); "; } return writedMethod+"("+fieldName+")"; } private String type2ParcelableReadData(String type, String fieldName, String readMethod, String className) { if ("boolean".equals(type) || "Boolean".equals(type)) { return fieldName+" = (1=="+readMethod+"() ? true : false)"; } String globalType = type2ParcelableAction(type); if ("Parcelable".equals(globalType)) { return fieldName+" = "+readMethod+"("+type+".class.getClassLoader())"; } if (isListOrArray(type)) { if (globalType.startsWith("Parcelable") && globalType.endsWith("List")) { StringBuilder strList = new StringBuilder(fieldName+" = new ArrayList<"+typeToParcelableRawType(type, false)+">();\n"); strList.append("\t\tin.readTypedList("+fieldName+", "+typeToParcelableRawType(type, false)+".CREATOR)"); return strList.toString(); } if ("Int".equals(typeToParcelableRawType(type, false)) && globalType.endsWith("List")) { return "in.readList("+fieldName+", Integer.class.getClassLoader())"; } if ("URI".equals(typeToParcelableRawType(type, false)) && globalType.endsWith("List")) { StringBuilder strList = new StringBuilder("List<String> "+fieldName+"StringList = new ArrayList<String>();\n"); strList.append("\t\t"+fieldName+" = new ArrayList<URI>();\n"); strList.append("\t\tin.readStringList("+fieldName+"StringList);\n"); strList.append("\t\ttry {\n"); strList.append("\t\t\tfor(int i=0; i<"+fieldName+"StringList.size(); i++) {\n"); strList.append("\t\t\t\t"+fieldName+".add(new URI("+fieldName+"StringList.get(i)));\n"); strList.append("\t\t\t}\n"); strList.append("\t\t} catch(URISyntaxException e) { System.out.println(\"Arg, can't create URI for field fileUris\"); }\n"); strList.append("\t\tint i=0"); return strList.toString(); } if ("Byte".equals(typeToParcelableRawType(type, false)) ) { String sByteCode = fieldName + " = new byte[in.readInt()];\n\t\t" + "in.readByteArray(" + fieldName + ")"; return sByteCode; } if (globalType.endsWith("List")) { return "if (null == "+fieldName+") { "+fieldName+" = new ArrayList(); }\n\t\t"+ readMethod+"("+fieldName+")"; } return readMethod+"("+fieldName+")"; } if ("URI".equals(typeToParcelableRawType(type, false))) { return "try { "+fieldName+" = new URI(in.readString()); } catch(URISyntaxException e) { System.out.println(\"Arg, can't create URI for field "+fieldName+"\"); }"; } if ("XMLGregorianCalendar".equals(typeToParcelableRawType(type, false))) { return "try { "+fieldName+" = DatatypeFactory.newInstance().newXMLGregorianCalendar(in.readString()); } catch(DatatypeConfigurationException e) { System.out.println(\"Arg, can't create XMLGregorianCalendar for field "+fieldName+"\"); }"; } if ("Date".equals(typeToParcelableRawType(type, false))) { return "DateFormat df = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss Z\");\n\t\ttry { " + fieldName + " = df.parse(in.readString()); } catch(java.text.ParseException pEx) { System.out.println(\"Arg, can't parse DateTime for field "+fieldName+"\"); }"; } return fieldName+" = "+readMethod+"()"; } private boolean isListOrArray(String type) { return type.endsWith("[]") || type.startsWith("List<"); } private String type2ParcelableAction(String type) { // -- Simple type String suffixe = ""; if (type.startsWith("List<")) { suffixe = "List"; type = type.replace("List<", ""); type = type.replace(">", ""); } if (type.endsWith("[]")) { suffixe = "Array"; type = type.replace("[]", ""); } return typeToParcelableGlobalType(type)+suffixe; } private String typeToParcelableGlobalType(String type, boolean rawTypeAreParcelable) { // Very simple Pattern patternSimpleType = Pattern.compile("(String|Float|Double|Long|Byte)"); Matcher matcherSimpleType = patternSimpleType.matcher(type); if (matcherSimpleType.find()) { return type; } if ("int".equals(type) || "Integer".equals(type) || "boolean".equals(type) || "Boolean".equals(type)) { return "Int"; } if ("double".equals(type)) { return "Double"; } if ("byte".equals(type)) { return "Byte"; } if ("float".equals(type)) { return "Float"; } if ("long".equals(type) ) { return "Long"; } // Manual steps if ("XMLGregorianCalendar".equals(type) || "URI".equals(type) || "Date".equals(type)) { return "String"; } // Parcelable if (rawTypeAreParcelable) { return "Parcelable"; } return type; } private String typeToParcelableRawType(String type, boolean rawTypeAreParcelable) { if (type.startsWith("List<")) { type = type.replace("List<", ""); type = type.replace(">", ""); } if (type.endsWith("[]")) { type = type.replace("[]", ""); } // Very simple Pattern patternSimpleType = Pattern.compile("(String|Float|Double|Long|Byte)"); Matcher matcherSimpleType = patternSimpleType.matcher(type); if (matcherSimpleType.find()) { return type; } if ("int".equals(type) || "Integer".equals(type) || "boolean".equals(type) || "Boolean".equals(type)) { return "Int"; } if ("double".equals(type)) { return "Double"; } if ("byte".equals(type)) { return "Byte"; } if ("float".equals(type)) { return "Float"; } if ("long".equals(type) ) { return "Long"; } // Manual steps if ("XMLGregorianCalendar".equals(type) || "URI".equals(type) || "Date".equals(type)) { return type; } // Parcelable if (rawTypeAreParcelable) { return "Parcelable"; } return type; } public String typeToParcelableGlobalType(String type) { return typeToParcelableGlobalType(type, true); } /** * Check if the pattern is found in a string * @param textToFind Text to find * @param textWhereToSearch Text where to find the pattern * @param flags Regex flags * @return True if the pattern is founded */ private static boolean isPatternMatching(String textToFind, String textWhereToSearch, int flags) { Pattern pattern = Pattern.compile(textToFind, flags); Matcher matcher = pattern.matcher(textWhereToSearch); return matcher.find(); } /** * Check if the pattern is found in a string * @param textToFind Text to find * @param textWhereToSearch Text where to find the pattern * @return True if the pattern is founded */ private static boolean isPatternMatching(String textToFind, String textWhereToSearch) { return isPatternMatching(textToFind, textWhereToSearch, Pattern.CASE_INSENSITIVE); } /**Replaces a regular expression with a specified string * @param schemaContent The string to check * @param textToFind Text to find * @param textToReplace Text to replace * @return Updated String with changes */ private static String findReplacePattern(String schemaContent, String textToFind, String textToReplace, int flags) { Pattern patternImport = Pattern.compile(textToFind, flags); Matcher matcherImport = patternImport.matcher(schemaContent); int i = matcherImport.groupCount(); return matcherImport.replaceAll(textToReplace); } private static String findReplacePattern(String schemaContent, String textToFind, String textToReplace) { return findReplacePattern(schemaContent, textToFind, textToReplace, Pattern.CASE_INSENSITIVE); } /** * Init parameters */ private void initParameters() { if (!folderOutputDirectory.equals(".") && !folderOutputDirectory.endsWith("/")) { folderOutputDirectory += "/"; } if (!folderInputDirectory.equals(".") && !folderInputDirectory.endsWith("/")) { folderInputDirectory += "/"; } } // Object factory processing code private static final Pattern elementDeclPattern = Pattern.compile("\\s*@XmlElementDecl\\(([^\\)]*)\\)"); private static final Pattern namespacePattern = Pattern.compile(".*namespace\\s*=\\s*\"([^\"]*)\".*"); private static final Pattern elementNamePattern = Pattern.compile(".*name\\s*=\\s*\"([^\"]*)\".*"); private static final String pkgDecl = "package "; private static final String COMMENT = "// This is a file generated by some gorgeous code in Jaxb2Simple.processObjectFactory(File objectFactoryFile) :("; private static final String IMPORT_NS = "import org.simpleframework.xml.Namespace;"; private static final String IMPORT_ROOT = "import org.simpleframework.xml.Root;"; private static final String ROOT_ANNOT = "@Root(name=\""; private static final String NS_ANNOT = "@Namespace(reference=\""; private static final String ANNOT_END = "\")"; private void processObjectFactory(File objectFactoryFile) throws IOException { HashSet<String> newClasses = new HashSet<String>(); File parentDirectory = objectFactoryFile.getParentFile(); String pkgName = null; BufferedReader br = new BufferedReader(new FileReader(objectFactoryFile)); while (true) { String line = br.readLine(); if (line==null) break; //getLog().debug("Going to match: '"+line+"'"); if (pkgName==null && line.startsWith(pkgDecl)) { pkgName = line.substring(pkgDecl.length(),line.length()-1); getLog().debug("Got package: '"+pkgName+"'"); } else { Matcher edm = elementDeclPattern.matcher(line); if (edm.matches()) { //getLog().debug("Found XmlElementDecl - parsing namespace and elementName of '"+edm.group(1)+"'"); Matcher nm = namespacePattern.matcher(edm.group(1)); if (nm.matches()) { Matcher enm = elementNamePattern.matcher(edm.group(1)); if (enm.matches()) { //getLog().debug("Bulding empty bean for {"+nm.group(1)+"}"+enm.group(1)); String newC = buildEmptySimpleXmlBean(parentDirectory, pkgName, nm.group(1), enm.group(1)); newClasses.add(newC); } } } } } newClassesOnPackage.put(pkgName,newClasses); br.close(); } private String buildEmptySimpleXmlBean(File directory, String pkgName, String namespace, String elementName) throws IOException { String className = classifyName(elementName); getLog().debug("Creating empty SimpleXML bean '"+pkgName+"."+className+" for element {'"+namespace+"}"+elementName+" in directory "+directory.getAbsolutePath()+"..."); File newBeanFile = new File(directory, className+".java"); newBeanFile.createNewFile(); // TODO check if className already exists PrintWriter filePw = new PrintWriter(new FileOutputStream(newBeanFile)); filePw.println(COMMENT); filePw.println(); filePw.println(pkgDecl+pkgName+";"); filePw.println(); filePw.println(IMPORT_NS); filePw.println(IMPORT_ROOT); filePw.println(); filePw.println(NS_ANNOT+namespace+ANNOT_END); filePw.println(ROOT_ANNOT+elementName+ANNOT_END); filePw.println("public class "+className+" {"); filePw.println("\tpublic "+className+"() {}"); filePw.println("}"); filePw.flush(); filePw.close(); return className; } private static String classifyName(String elementName) { // TODO properly, using com.sun.codemodel.JCodeModel and so on String[] parts = elementName.split("-|_"); StringBuilder sb = new StringBuilder(); for (int i=0; i<parts.length; i++) { sb.append(Character.toUpperCase(parts[i].charAt(0))); sb.append(parts[i].substring(1)); } return sb.toString(); } private void processPackageInfo(File javaFile) throws IOException { String pkgName = null; String ns = null; BufferedReader br = new BufferedReader(new FileReader(javaFile)); while (true) { String line = br.readLine(); if (line==null) break; if (pkgName==null && line.startsWith(pkgDecl)) { pkgName = line.substring(pkgDecl.length(),line.length()-1); getLog().debug("Got package: '"+pkgName+"'"); } if (ns==null) { Matcher nm = namespacePattern.matcher(line); if (nm.matches()) ns = nm.group(1); } if (pkgName!=null && ns!=null) { namespaceForPackage.put(pkgName, ns); return; } } } }