Changeset 3481


Ignore:
Timestamp:
12/14/07 16:39:42 (12 years ago)
Author:
curtis
Message:

Use Velocity template engine for metadata logic autogenerator.

Location:
trunk
Files:
10 added
5 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/build.properties

    r3432 r3481  
    2727           jar/omero-client.jar:\ 
    2828           jar/poi-loci.jar:\ 
     29           jar/velocity-dep-1.5.jar:\ 
    2930           jar/visad-lite.jar 
    3031 
  • trunk/loci/formats/auto/MetadataAutogen.java

    r3422 r3481  
    2828import java.text.DateFormat; 
    2929import java.util.*; 
     30import org.apache.velocity.app.VelocityEngine; 
     31import org.apache.velocity.Template; 
     32import org.apache.velocity.VelocityContext; 
    3033 
    3134/** 
     
    4346  // -- Constants -- 
    4447 
    45   public static final String STORE_SRC = "MetadataAutogenHeaderStore.txt"; 
    46   public static final String RETRIEVE_SRC = "MetadataAutogenHeaderRetrieve.txt"; 
    47   public static final String OMEXML_SRC = "MetadataAutogenHeaderOMEXML.txt"; 
    48   public static final String GLOBAL_SRC = "MetadataAutogenGlobal.txt"; 
    49   public static final String NODES_SRC = "MetadataAutogenNodes.txt"; 
    50  
    51   // -- Static fields -- 
    52  
    53   private static Hashtable versions; 
    54   private static Hashtable basicVars; 
    55   private static String storeHeader; 
    56   private static String retrieveHeader; 
    57   private static String omexmlHeader; 
    58   private static OutFiles out = new OutFiles(); 
    59   private static HashSet getters = new HashSet(); 
    60   private static HashSet setters = new HashSet(); 
    61   private static HashSet helpers = new HashSet(); 
    62   private static Hashtable paramMap = new Hashtable(); 
     48  /** Path to versions definition file. */ 
     49  public static final String VERSION_SRC = "MetadataAutogenVersions.txt"; 
     50 
     51  /** Path to entities definition file. */ 
     52  public static final String ENTITY_SRC = "MetadataAutogenEntities.txt"; 
    6353 
    6454  // -- Main method -- 
    6555 
    66   public static void main(String[] args) throws IOException { 
    67     System.out.print("Parsing input files... "); 
     56  public static void main(String[] args) throws Exception { 
     57    // create needed directories 
    6858    File ome = new File("ome"); 
    6959    if (!ome.exists()) ome.mkdir(); 
    70  
    71     // parse global input file 
    72     versions = parseGlobal(); 
    73  
    74     // parse header input files 
    75     storeHeader = parseHeader(STORE_SRC); 
    76     retrieveHeader = parseHeader(RETRIEVE_SRC); 
    77     omexmlHeader = parseHeader(OMEXML_SRC); 
    78  
    79     // parse nodes input file 
    80     Vector nodes = parseNodes(); 
    81  
    82     System.out.println("done."); 
    83     System.out.println("Generating classes..."); 
    84  
    85     // generate classes 
    86     for (int i=0; i<nodes.size(); i++) { 
    87       Node node = (Node) nodes.get(i); 
    88       doGetters(node); 
    89     } 
    90     for (int i=0; i<nodes.size(); i++) { 
    91       Node node = (Node) nodes.get(i); 
    92       doSetters(node); 
    93     } 
    94     for (int i=0; i<nodes.size(); i++) { 
    95       Node node = (Node) nodes.get(i); 
    96       doHelpers(node); 
    97     } 
    98     out.closeFiles(); 
    99  
    100     System.out.println("Autogeneration complete."); 
    101   } 
    102  
    103   // -- Helper methods -- 
    104  
    105   private static Hashtable parseGlobal() throws IOException { 
    106     Hashtable hash = new Hashtable(); 
    107     String user = System.getProperty("user.name"); 
     60    File meta = new File("meta"); 
     61    if (!meta.exists()) meta.mkdir(); 
     62 
     63    // initialize Velocity engine; enable loading of templates as resources 
     64    VelocityEngine ve = new VelocityEngine(); 
     65    Properties p = new Properties(); 
     66    p.setProperty("resource.loader", "class"); 
     67    p.setProperty("class.resource.loader.class", 
     68      "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); 
     69    ve.init(p); 
     70 
     71    // populate Velocity context 
     72    VelocityContext context = new VelocityContext(); 
     73    context.put("name", "World"); 
     74    context.put("user", System.getProperty("user.name")); 
    10875    DateFormat dateFmt = DateFormat.getDateInstance(DateFormat.MEDIUM); 
    10976    DateFormat timeFmt = DateFormat.getTimeInstance(DateFormat.LONG); 
    11077    Date date = Calendar.getInstance().getTime(); 
    111     String timestamp = dateFmt.format(date) + " " + timeFmt.format(date); 
    112  
    113     basicVars = new Hashtable(); 
    114     basicVars.put("user", user); 
    115     basicVars.put("timestamp", timestamp); 
    116  
    117     String version = null; 
     78    context.put("timestamp", dateFmt.format(date) + " " + timeFmt.format(date)); 
     79 
     80    // parse versions file 
     81    Hashtable versions = parseVersions(); 
     82 
     83    // parse entities file 
     84    Vector entities = parseEntities(); 
     85    context.put("entities", entities); 
     86 
     87    // process templates 
     88    processTemplate(ve, context, 
     89      "MetadataStore.vm", "meta/MetadataStore.java"); 
     90    processTemplate(ve, context, 
     91      "MetadataRetrieve.vm", "meta/MetadataRetrieve.java"); 
     92    processTemplate(ve, context, 
     93      "DummyMetadata.vm", "meta/DummyMetadata.java"); 
     94    processTemplate(ve, context, 
     95      "AggregateMetadata.vm", "meta/AggregateMetadata.java"); 
     96 
     97    Enumeration versionKeys = versions.keys(); 
     98    while (versionKeys.hasMoreElements()) { 
     99      String versionKey = (String) versionKeys.nextElement(); 
     100 
     101      // first entity with each distinct path end node for this version 
     102      HashSet nodes = new HashSet(); 
     103      Vector unique = new Vector(); 
     104      for (int i=0; i<entities.size(); i++) { 
     105        Entity entity = (Entity) entities.get(i); 
     106        String last = entity.last(versionKey); 
     107        if (nodes.contains(last) || last.equals("-")) continue; 
     108        nodes.add(last); 
     109        unique.add(entity); 
     110      } 
     111      context.put("unique", unique); 
     112 
     113      Hashtable vars = (Hashtable) versions.get(versionKey); 
     114      // update context 
     115      context.put("versionKey", versionKey); 
     116      Enumeration varKeys = vars.keys(); 
     117      while (varKeys.hasMoreElements()) { 
     118        String name = (String) varKeys.nextElement(); 
     119        String value = (String) vars.get(name); 
     120        context.put(name, value); 
     121      } 
     122      processTemplate(ve, context, 
     123        "OMEXMLMetadata.vm", "ome/OMEXML" + versionKey + "Metadata.java"); 
     124    } 
     125  } 
     126 
     127  // -- Helper methods -- 
     128 
     129  private static void processTemplate(VelocityEngine ve, 
     130    VelocityContext context, String inFile, String outFile) 
     131    // NB: No choice, as VelocityEngine.getTemplate(String) throws Exception 
     132    throws Exception 
     133  { 
     134    System.out.print("Writing " + outFile + ": "); 
     135    Template t = ve.getTemplate("loci/formats/auto/" + inFile); 
     136    StringWriter writer = new StringWriter(); 
     137    t.merge(context, writer); 
     138    PrintWriter out = new PrintWriter(new FileWriter(outFile)); 
     139    out.print(writer.toString()); 
     140    out.close(); 
     141    System.out.println("done."); 
     142  } 
     143 
     144  private static Hashtable parseVersions() throws IOException { 
     145    System.out.println("Reading " + VERSION_SRC + ":"); 
     146    Hashtable versions = new Hashtable(); 
     147 
     148    String versionKey = null; 
    118149    Hashtable vars = null; 
    119150    BufferedReader in = new BufferedReader(new InputStreamReader( 
    120       MetadataAutogen.class.getResourceAsStream(GLOBAL_SRC))); 
     151      MetadataAutogen.class.getResourceAsStream(VERSION_SRC))); 
    121152    while (true) { 
    122153      String line = in.readLine(); 
     
    129160      if (line.startsWith("[")) { 
    130161        // version header 
    131         if (version != null) hash.put(version, vars); 
     162        if (versionKey != null) versions.put(versionKey, vars); 
    132163        if (line.startsWith("[-")) break; 
    133         version = line.substring(1, line.length() - 1); 
     164        versionKey = line.substring(1, line.length() - 1); 
    134165        vars = new Hashtable(); 
    135         vars.put("user", user); 
    136         vars.put("timestamp", timestamp); 
     166        System.out.println("\t" + versionKey); 
    137167        continue; 
    138168      } 
     
    143173    } 
    144174    in.close(); 
    145     return hash; 
    146   } 
    147  
    148   private static String parseHeader(String id) throws IOException { 
     175    return versions; 
     176  } 
     177 
     178  public static Vector parseEntities() throws IOException { 
     179    System.out.println("Reading " + ENTITY_SRC + ":"); 
     180    Vector entities = new Vector(); 
     181    Entity entity = null; 
     182    Property prop = null; 
    149183    BufferedReader in = new BufferedReader(new InputStreamReader( 
    150       MetadataAutogen.class.getResourceAsStream(id))); 
    151     StringBuffer sb = new StringBuffer(); 
    152     while (true) { 
    153       String line = in.readLine(); 
    154       if (line == null) break; 
    155       sb.append(line); 
    156       sb.append("\n"); 
    157     } 
    158     in.close(); 
    159     return sb.toString(); 
    160   } 
    161  
    162   private static Vector parseNodes() throws IOException { 
    163     Vector nodes = new Vector(); 
    164     Node node = null; 
    165     Param param = null; 
    166     BufferedReader in = new BufferedReader(new InputStreamReader( 
    167       MetadataAutogen.class.getResourceAsStream(NODES_SRC))); 
     184      MetadataAutogen.class.getResourceAsStream(ENTITY_SRC))); 
    168185    while (true) { 
    169186      String line = in.readLine(); 
     
    175192 
    176193      if (line.startsWith("[")) { 
    177         // node header 
    178         if (node != null) nodes.add(node); 
     194        // entity header 
     195        if (entity != null) entities.add(entity); 
    179196        if (line.startsWith("[-")) break; 
    180         node = new Node(); 
    181         node.name = line.substring(1, line.length() - 1); 
    182         node.desc = in.readLine(); 
    183         node.extra = in.readLine(); 
     197        String name = line.substring(1, line.length() - 1); 
     198        String desc = in.readLine(); 
     199        String extra = in.readLine(); 
     200        entity = new Entity(name, desc, extra); 
     201        System.out.println("\t" + name); 
    184202        continue; 
    185203      } 
     
    191209          continue; 
    192210        } 
    193         String version = line.substring(1, colon).trim(); 
    194         String paramName = line.substring(colon + 1).trim(); 
    195         paramMap.put(version + ":" + node.name + ":" + param.name, paramName); 
     211        String versionKey = line.substring(1, colon).trim(); 
     212        String propName = line.substring(colon + 1).trim(); 
     213        prop.addMappedName(versionKey, propName); 
    196214        continue; 
    197215      } 
     
    200218      if (colon >= 0) { 
    201219        // path to XML element for a particular schema version 
    202         String version = line.substring(0, colon).trim(); 
     220        String versionKey = line.substring(0, colon).trim(); 
    203221        String path = line.substring(colon + 1).trim(); 
    204         if (version.equalsIgnoreCase("Default")) { 
    205           // populate all known versions with the default 
    206           Enumeration en = versions.keys(); 
    207           Vector indices = getIndices(path); 
    208           while (en.hasMoreElements()) { 
    209             String key = (String) en.nextElement(); 
    210             if (!node.paths.contains(key)) node.paths.put(key, path); 
    211             node.indices = indices; 
    212           } 
    213         } 
    214         else node.paths.put(version, path); 
     222        entity.addPath(versionKey, path); 
    215223        continue; 
    216224      } 
     
    224232      } 
    225233 
    226       // parameter 
    227       param = new Param(); 
    228       param.type = st.nextToken(); 
    229       param.name = st.nextToken(); 
     234      // property 
     235      String propType = st.nextToken(); 
     236      String propName = st.nextToken(); 
    230237      StringBuffer sb = new StringBuffer(); 
    231238      if (st.hasMoreTokens()) sb.append(st.nextToken()); 
     
    234241        sb.append(st.nextToken()); 
    235242      } 
    236       param.doc = sb.toString(); 
    237       node.params.add(param); 
     243      String propDoc = sb.toString(); 
     244      prop = new Property(propName, propType, propDoc, entity, false); 
    238245    } 
    239246    in.close(); 
    240     return nodes; 
    241   } 
    242  
    243   /** Generates getter methods for each output source file. */ 
    244   private static void doGetters(Node node) throws IOException { 
    245     boolean first = true; 
    246     Enumeration e = node.paths.keys(); 
    247     while (e.hasMoreElements()) { 
    248       String key = (String) e.nextElement(); 
    249       String value = (String) node.paths.get(key); 
    250       if (first) { 
    251         // MetadataRetrieve interface 
    252         doGetters("MetadataRetrieve.java", value, node, null); 
    253         first = false; 
    254       } 
    255       // OME-XML implementations 
    256       doGetters("ome/OMEXML" + key + "Metadata.java", value, node, key); 
    257     } 
    258   } 
    259  
    260   /** Generates setter methods for each output source file. */ 
    261   private static void doSetters(Node node) throws IOException { 
    262     boolean first = true; 
    263     Enumeration e = node.paths.keys(); 
    264     while (e.hasMoreElements()) { 
    265       String key = (String) e.nextElement(); 
    266       String value = (String) node.paths.get(key); 
    267       if (first) { 
    268         // MetadataStore interface 
    269         doSetters("MetadataStore.java", value, node, null); 
    270         first = false; 
    271       } 
    272       // OME-XML implementation 
    273       doSetters("ome/OMEXML" + key + "Metadata.java", value, node, key); 
    274     } 
    275   } 
    276  
    277   /** Generates helper methods for each output source file. */ 
    278   private static void doHelpers(Node node) throws IOException { 
    279     Enumeration e = node.paths.keys(); 
    280     while (e.hasMoreElements()) { 
    281       String key = (String) e.nextElement(); 
    282       String value = (String) node.paths.get(key); 
    283       // OME-XML implementation 
    284       String id = "ome/OMEXML" + key + "Metadata.java"; 
    285       doHelpers(id, value, node.indices, key); 
    286     } 
    287   } 
    288  
    289   /** Generates getter methods for the given node and source file. */ 
    290   private static void doGetters(String id, String path, Node node, 
    291     String version) throws IOException 
    292   { 
    293     String end = version == null ? ");" : ")"; 
    294     LineTracker lt = new LineTracker(); 
    295  
    296     // prepend getters section comment 
    297     if (version != null && !getters.contains(id)) { 
    298       getters.add(id); 
    299       lt.add("  // -- MetadataRetrieve API methods --"); 
    300       lt.newline(); 
    301       lt.newline(); 
    302     } 
    303  
    304     // parse path 
    305     String last = getLastPathElement(path); 
    306     Vector indices = node.indices; 
    307     int psize = node.params.size(); 
    308     int isize = indices.size(); 
    309  
    310     lt.add("  // - " + node.name + " attribute retrieval -"); 
    311     lt.newline(); 
    312     lt.newline(); 
    313  
    314     for (int i=0; i<psize; i++) { 
    315       Param pi = (Param) node.params.get(i); 
    316       String piName = stripPrefix(pi.name); 
    317       if (i > 0) lt.newline(); 
    318  
    319       // javadoc 
    320       if (version == null) { 
    321         lt.add("  /**"); 
    322         lt.newline(); 
    323         lt.add("   * Gets "); 
    324         lt.addTokens(pi.doc + " for a particular " + node.name + ".", "   * "); 
    325         lt.newline(); 
    326         for (int j=0; j<isize; j++) { 
    327           Param pj = (Param) indices.get(j); 
    328           String pjName = stripPrefix(pj.name); 
    329           lt.add("   * @param " + toVarName(pjName) + " "); 
    330           lt.addTokens(pj.doc + ".", "   *   "); 
    331           lt.newline(); 
    332         } 
    333         lt.add("   */"); 
    334         lt.newline(); 
    335       } 
    336       else { 
    337         String lead = "@see loci.formats.MetadataRetrieve#get" + 
    338           node.name + piName + "("; 
    339         StringBuffer sb = new StringBuffer(); 
    340         for (int j=0; j<isize; j++) { 
    341           Param pj = (Param) indices.get(j); 
    342           sb.append(pj.type); 
    343           sb.append(j < isize - 1 ? ", " : ")"); 
    344         } 
    345         if (lead.length() + sb.length() <= 72) { 
    346           lt.add("  /* "); 
    347           lt.addTokens(lead + sb.toString(), null); 
    348           lt.add(" */"); 
    349           lt.newline(); 
    350         } 
    351         else { 
    352           lt.add("  /*"); 
    353           lt.newline(); 
    354           lt.add("   * "); 
    355           lt.addTokens(lead + " " + sb.toString(), "   *   "); 
    356           lt.newline(); 
    357           lt.add("   */"); 
    358           lt.newline(); 
    359         } 
    360       } 
    361       // method signature 
    362       lt.add("  "); 
    363       if (version != null) lt.add("public "); 
    364       lt.add(pi.type + " get" + node.name + piName + "("); 
    365       for (int j=0; j<isize; j++) { 
    366         // parameters 
    367         Param pj = (Param) indices.get(j); 
    368         lt.add(pj.getArg(true, true, j == 0, j == isize - 1, end), "    "); 
    369       } 
    370       if (version != null) { 
    371         // opening brace 
    372         if (lt.hasWrapped()) { 
    373           lt.newline(); 
    374           lt.add(" "); 
    375         } 
    376         lt.add(" {", "  "); 
    377       } 
    378       lt.newline(); 
    379  
    380       // method body 
    381       if (version != null) { 
    382         boolean noSupport = last.equals("-"); 
    383         String mappedName = getParamName(pi.name, node.name, version); 
    384         if (noSupport || mappedName.equals("-")) { 
    385           Hashtable vars = (Hashtable) versions.get(version); 
    386           lt.add("    // NB: " + (noSupport ? node.name : piName) + 
    387             " unsupported for schema version " + vars.get("version")); 
    388           lt.newline(); 
    389           lt.add("    return null;"); 
    390           lt.newline(); 
    391         } 
    392         else { 
    393           String prefix = getPrefix(mappedName); 
    394           mappedName = stripPrefix(mappedName); 
    395           String lastVar = toVarName(last); 
    396           lt.add("    " + last + "Node " + lastVar + " = get" + last + "("); 
    397           for (int j=0; j<isize; j++) { 
    398             Param pj = (Param) indices.get(j); 
    399             lt.add(pj.getArg(true, false, j == 0, false, null), "      "); 
    400           } 
    401           lt.add(" false);", "      "); 
    402           lt.newline(); 
    403           String ante = "    return " + lastVar + " == null ? null :"; 
    404  
    405           boolean convert = false; 
    406           if (mappedName.endsWith("%")) { 
    407             mappedName = mappedName.substring(0, mappedName.length() - 1); 
    408             convert = true; 
    409           } 
    410           String cons = lastVar + "." + prefix + mappedName + "()"; 
    411           if (convert) { 
    412             cons = toVarName(node.name) + 
    413               mappedName + "To" + pi.type + "(" + cons + ")"; 
    414           } 
    415           cons += ";"; 
    416           if (ante.length() + cons.length() <= 79) { 
    417             lt.add(ante + " " + cons); 
    418             lt.newline(); 
    419           } 
    420           else { 
    421             lt.add(ante); 
    422             lt.newline(); 
    423             lt.add("      " + cons); 
    424             lt.newline(); 
    425           } 
    426         } 
    427         // closing brace 
    428         lt.add("  }"); 
    429         lt.newline(); 
    430       } 
    431     } 
    432  
    433     // output results 
    434     out.write(id, lt.toString()); 
    435   } 
    436  
    437   /** Generates setter methods for the given node and source file. */ 
    438   private static void doSetters(String id, String path, Node node, 
    439     String version) throws IOException 
    440   { 
    441     String end = version == null ? ");" : ")"; 
    442     LineTracker lt = new LineTracker(); 
    443  
    444     // prepend setters section comment 
    445     if (version != null && !setters.contains(id)) { 
    446       setters.add(id); 
    447       lt.add("  // -- MetadataStore API methods --"); 
    448       lt.newline(); 
    449       lt.newline(); 
    450     } 
    451  
    452     // parse path 
    453     String last = getLastPathElement(path); 
    454     Vector indices = node.indices; 
    455     int psize = node.params.size(); 
    456     int isize = indices.size(); 
    457     int total = psize + isize; 
    458  
    459     // javadoc 
    460     if (version == null) { 
    461       lt.add("  /**"); 
    462       lt.newline(); 
    463       lt.add("   * Sets "); 
    464       lt.addTokens(node.desc + ".", "   * "); 
    465       if (!node.extra.equals("-")) { 
    466         lt.add(" ", "   *"); 
    467         lt.addTokens(node.extra, "   * "); 
    468       } 
    469       lt.newline(); 
    470       for (int i=0; i<total; i++) { 
    471         Param p = (Param) 
    472           (i < psize ? node.params.get(i) : indices.get(i - psize)); 
    473         String pName = stripPrefix(p.name); 
    474         lt.add("   * @param " + toVarName(pName) + " "); 
    475         lt.addTokens(p.doc + ".", "   *   "); 
    476         lt.newline(); 
    477       } 
    478       lt.add("   */"); 
    479       lt.newline(); 
    480     } 
    481     else { 
    482       String lead = "@see loci.formats.MetadataStore#set" + node.name + "("; 
    483       StringBuffer sb = new StringBuffer(); 
    484       for (int i=0; i<total; i++) { 
    485         Param p = (Param) 
    486           (i < psize ? node.params.get(i) : indices.get(i - psize)); 
    487         sb.append(p.type); 
    488         sb.append(i < total - 1 ? ", " : ")"); 
    489       } 
    490       if (lead.length() + sb.length() <= 72) { 
    491         lt.add("  /* " + lead + sb.toString() + " */"); 
    492         lt.newline(); 
    493       } 
    494       else { 
    495         lt.add("  /*"); 
    496         lt.newline(); 
    497         lt.add("   * "); 
    498         lt.addTokens(lead + " " + sb.toString(), "   *   "); 
    499         lt.newline(); 
    500         lt.add("   */"); 
    501         lt.newline(); 
    502       } 
    503     } 
    504     // method signature 
    505     lt.add("  "); 
    506     if (version != null) lt.add("public "); 
    507     lt.add("void set" + node.name + "("); 
    508     for (int i=0; i<total; i++) { 
    509       // parameters 
    510       Param p = (Param) 
    511         (i < psize ? node.params.get(i) : indices.get(i - psize)); 
    512       lt.add(p.getArg(true, true, i == 0, i == total - 1, end), "    "); 
    513     } 
    514     if (version != null) { 
    515       // opening brace 
    516       if (lt.hasWrapped()) { 
    517         lt.newline(); 
    518         lt.add(" "); 
    519       } 
    520       lt.add(" {", "  "); 
    521     } 
    522     lt.newline(); 
    523  
    524     // method body 
    525     if (version != null) { 
    526       boolean noSupport = last.equals("-"); 
    527       if (noSupport) { 
    528         Hashtable vars = (Hashtable) versions.get(version); 
    529         lt.add("    // NB: " + node.name + 
    530           " unsupported for schema version " + vars.get("version")); 
    531         lt.newline(); 
    532       } 
    533       else { 
    534         String lastVar = toVarName(last); 
    535         lt.add("    " + last + "Node " + lastVar + 
    536           " = get" + last + "("); 
    537         for (int i=0; i<isize; i++) { 
    538           Param p = (Param) indices.get(i); 
    539           lt.add(p.getArg(true, false, i == 0, false, null), "    "); 
    540         } 
    541         lt.add(" true);", "      "); 
    542         lt.newline(); 
    543         for (int i=0; i<psize; i++) { 
    544           Param p = (Param) node.params.get(i); 
    545           String mappedName = getParamName(p.name, node.name, version); 
    546           if (mappedName.equals("-")) { 
    547             Hashtable vars = (Hashtable) versions.get(version); 
    548             lt.add("    // NB: " + p.name + 
    549               " unsupported for schema version " + vars.get("version")); 
    550             lt.newline(); 
    551           } 
    552           else { 
    553             String prefix = getPrefix(mappedName); 
    554             mappedName = stripPrefix(mappedName); 
    555             String varName = toVarName(stripPrefix(p.name)); 
    556             String ante = "    if (" + varName + " != null) "; 
    557             boolean convert = false; 
    558             if (mappedName.endsWith("%")) { 
    559               mappedName = mappedName.substring(0, mappedName.length() - 1); 
    560               convert = true; 
    561             } 
    562             String cons = varName; 
    563             if (convert) { 
    564               cons = toVarName(node.name) + 
    565                 mappedName + "From" + p.type + "(" + cons + ")"; 
    566             } 
    567             cons = lastVar + ".set" + mappedName + "(" + cons + ");"; 
    568             if (ante.length() + cons.length() <= 80) { 
    569               lt.add(ante + cons); 
    570               lt.newline(); 
    571             } 
    572             else { 
    573               lt.add(ante + "{"); 
    574               lt.newline(); 
    575               lt.add("      " + cons); 
    576               lt.newline(); 
    577               lt.add("    }"); 
    578               lt.newline(); 
    579             } 
    580           } 
    581         } 
    582       } 
    583       // closing brace 
    584       lt.add("  }"); 
    585       lt.newline(); 
    586     } 
    587  
    588     // output results 
    589     out.write(id, lt.toString()); 
    590   } 
    591  
    592   /** Generates helper methods for the given node and source file. */ 
    593   private static void doHelpers(String id, 
    594     String path, Vector indices, String version) throws IOException 
    595   { 
    596     // only generate each path's helper method once 
    597     if (helpers.contains(id + ":" + path)) return; 
    598     helpers.add(id + ":" + path); 
    599  
    600     String end = ")"; 
    601     LineTracker lt = new LineTracker(); 
    602  
    603     // prepend helpers section comment 
    604     if (!helpers.contains(id)) { 
    605       helpers.add(id); 
    606       lt.add("  // -- Helper methods --"); 
    607       lt.newline(); 
    608       lt.newline(); 
    609     } 
    610  
    611     // parse path 
    612     String last = getLastPathElement(path); 
    613     int isize = indices.size(); 
    614  
    615     if (last.equals("-")) return; // unsupported node type for this version 
    616  
    617     // parse version-specific configuration 
    618     Hashtable vars = (Hashtable) versions.get(version); 
    619     boolean legacy = "true".equals(vars.get("legacy")); 
    620  
    621     // method signature 
    622     lt.add("  // " + path); 
    623     lt.newline(); 
    624     lt.add("  private " + last + "Node get" + last + "("); 
    625     for (int i=0; i<isize; i++) { 
    626       // parameters 
    627       StringBuffer sb = new StringBuffer(); 
    628       if (i > 0) sb.append(" "); 
    629       Param p = (Param) indices.get(i); 
    630       sb.append(p.type); 
    631       sb.append(" "); 
    632       sb.append(toVarName(p.name)); 
    633       sb.append(","); 
    634       lt.add(sb.toString(), "    "); 
    635     } 
    636     lt.add(" boolean create)", "    "); 
    637     // opening brace 
    638     if (lt.hasWrapped()) { 
    639       lt.newline(); 
    640       lt.add(" "); 
    641     } 
    642     lt.add(" {", "  "); 
    643     lt.newline(); 
    644  
    645     // method body 
    646     lt.add("    int ndx, count;"); 
    647     lt.newline(); 
    648     lt.add("    List list;"); 
    649     lt.newline(); 
    650     lt.add("    // get OME node"); 
    651     lt.newline(); 
    652     lt.add("    OMENode ome = (OMENode) root;"); 
    653     lt.newline(); 
    654  
    655     String var = "ome"; 
    656     String pVar = "ome", pToken = "OME"; 
    657     String endElement = null, endVar = null; 
    658     int multiCount = 0; 
    659     StringTokenizer st = new StringTokenizer(path, "/"); 
    660     while (st.hasMoreTokens()) { 
    661       String token = st.nextToken(); 
    662       boolean ref = false, bang = false; 
    663       if (token.startsWith("@")) { 
    664         if (token.startsWith("@!")) { 
    665           token = token.substring(2); 
    666           bang = true; 
    667         } 
    668         else token = token.substring(1); 
    669         ref = true; 
    670       } 
    671       boolean multi = false; 
    672       if (token.endsWith("+")) { 
    673         token = token.substring(0, token.length() - 1); 
    674         multi = true; 
    675       } 
    676       var = toVarName(token); 
    677       lt.add("    // get " + token + " node"); 
    678       lt.newline(); 
    679       boolean ca = pVar.equals("ca"); 
    680       if (token.equals("CA")) token = "CustomAttributes"; 
    681       if (multi) { 
    682         Param indexParam = (Param) indices.get(multiCount++); 
    683         lt.add("    ndx = i2i(" + toVarName(indexParam.name) + ");"); 
    684         lt.newline(); 
    685         if (ca) { 
    686           lt.add("    count = " + pVar + ".countCAList(\"" + token + "\");"); 
    687         } 
    688         else if (legacy) { 
    689           lt.add("    count = " + pVar + ".count" + token + "List();"); 
    690         } 
    691         else lt.add("    count = " + pVar + ".get" + token + "Count();"); 
    692         lt.newline(); 
    693         lt.add("    if (!create && ndx >= count) return null;"); 
    694         lt.newline(); 
    695         if (ref) { 
    696           lt.add("    for (int i=count; i<=ndx; i++) {"); 
    697           lt.newline(); 
    698           lt.add("      new " + token + 
    699             "Node(ca).set" + pToken + "(" + pVar + ");"); 
    700           lt.newline(); 
    701           lt.add("    }"); 
    702           lt.newline(); 
    703         } 
    704         else { 
    705           lt.add("    for (int i=count; i<=ndx; i++) new " + 
    706             token + "Node(" + pVar + ");"); 
    707           lt.newline(); 
    708         } 
    709         if (ca) { 
    710           lt.add("    list = " + pVar + "." + "getCAList(\"" + token + "\");"); 
    711         } 
    712         else lt.add("    list = " + pVar + ".get" + token + "List();"); 
    713         lt.newline(); 
    714         lt.add("    " + token + "Node " + var + 
    715           " = (" + token + "Node) list.get(ndx);"); 
    716         lt.newline(); 
    717       } 
    718       else { 
    719         if (ca || ref) { 
    720           String extra = bang ? "By" + pToken : ""; 
    721           lt.add("    " + token + "Node " + var + " = null;"); 
    722           lt.newline(); 
    723           if (ca) lt.add("    count = ca.countCAList(\"" + token + "\");"); 
    724           else { 
    725             lt.add("    count = " + pVar + 
    726               ".count" + token + "List" + extra + "();"); 
    727           } 
    728           lt.newline(); 
    729           lt.add("    if (count >= 1) {"); 
    730           lt.newline(); 
    731           lt.add("      " + var + " = (" + token + "Node)"); 
    732           if (ca) { 
    733             lt.add(" ca.getCAList(\"" + token + "\").get(0);", "        "); 
    734           } 
    735           else { 
    736             lt.add(" " + pVar + ".get" + token + 
    737               "List" + extra + "().get(0);", "        "); 
    738           } 
    739           lt.newline(); 
    740           lt.add("    }"); 
    741         } 
    742         else { 
    743           lt.add("    " + token + "Node " + var + 
    744             " = " + pVar + ".get" + token + "();"); 
    745         } 
    746         lt.newline(); 
    747         lt.add("    if (" + var + " == null) {"); 
    748         lt.newline(); 
    749         lt.add("      if (!create) return null;"); 
    750         lt.newline(); 
    751         lt.add("      " + var + " = new " + token + 
    752           "Node(" + (ref ? "ca" : pVar) + ");"); 
    753         lt.newline(); 
    754         if (ref) { 
    755           lt.add("      " + var + ".set" + pToken + "(" + pVar + ");"); 
    756           lt.newline(); 
    757         } 
    758         lt.add("    }"); 
    759         lt.newline(); 
    760       } 
    761       pToken = token; 
    762       pVar = var; 
    763     } 
    764     lt.add("    return " + var + ";"); 
    765     lt.newline(); 
    766  
    767     // closing brace 
    768     lt.add("  }"); 
    769     lt.newline(); 
    770     // output results 
    771     out.write(id, lt.toString()); 
    772   } 
    773  
    774   /** Converts attribute name in CamelCase to variable in variableCase. */ 
    775   private static String toVarName(String attr) { 
    776     char[] c = attr.toCharArray(); 
    777     for (int i=0; i<c.length; i++) { 
    778       if (c[i] >= 'A' && c[i] <= 'Z') c[i] += 'a' - 'A'; 
    779       else { 
    780         if (i > 1) c[i - 1] += 'A' - 'a'; // keep last character capitalized 
    781         break; 
    782       } 
    783     } 
    784     return new String(c); 
    785   } 
    786  
    787   /** Strips off any lower case prefix from the given attribute name. */ 
    788   private static String stripPrefix(String attr) { 
    789     char[] c = attr.toCharArray(); 
    790     int i = 0; 
    791     while (i < c.length && c[i] >= 'a' && c[i] <= 'z') i++; 
    792     return i > 0 ? attr.substring(i) : attr; 
    793   } 
    794  
    795   /** Gets any lower case prefix from the given attribute name. */ 
    796   private static String getPrefix(String attr) { 
    797     char[] c = attr.toCharArray(); 
    798     int i = 0; 
    799     while (i < c.length && c[i] >= 'a' && c[i] <= 'z') i++; 
    800     return i > 0 ? attr.substring(0, i) : "get"; 
    801   } 
    802  
    803   /** Gets parameter list corresponding to needed indices for a node. */ 
    804   private static Vector getIndices(String path) { 
    805     Vector indices = new Vector(); 
    806     if (path != null) { 
    807       StringTokenizer st = new StringTokenizer(path, "/>"); 
    808       int tokens = st.countTokens(); 
    809       for (int i=0; i<tokens; i++) { 
    810         String t = st.nextToken(); 
    811         if (t.endsWith("+")) { 
    812           Param p = new Param(); 
    813           t = t.substring(t.startsWith("@") ? 1 : 0, t.length() - 1); 
    814           p.name = t + "Index"; 
    815           p.type = "Integer"; 
    816           p.doc = "index of the " + t; 
    817           indices.add(p); 
    818         } 
    819       } 
    820     } 
    821     return indices; 
    822   } 
    823  
    824   /** Writes header for the given output source file. */ 
    825   private static void writeHeader(String id) throws IOException { 
    826     System.out.println(id); 
    827  
    828     String header = null; 
    829     Hashtable vars = null; 
    830     if (id.startsWith("MetadataStore")) { 
    831       header = storeHeader; 
    832       vars = basicVars; 
    833     } 
    834     else if (id.startsWith("MetadataRetrieve")) { 
    835       header = retrieveHeader; 
    836       vars = basicVars; 
    837     } 
    838     else { // id.startsWith("ome/OMEXML") 
    839       header = omexmlHeader; 
    840       vars = (Hashtable) versions.get(id.substring(10, id.length() - 13)); 
    841     } 
    842     header = filterHeader(header, vars); 
    843     out.write(id, header); 
    844   } 
    845  
    846   /** Writes footer for the given output source file. */ 
    847   private static void writeFooter(String id) throws IOException { 
    848     out.write(id, "}"); 
    849   } 
    850  
    851   /** 
    852    * Filters tokens for the given header, filling in 
    853    * the values from the specified hashtable. 
    854    */ 
    855   private static String filterHeader(String header, Hashtable vars) { 
    856     Enumeration e = vars.keys(); 
    857     while (e.hasMoreElements()) { 
    858       String key = (String) e.nextElement(); 
    859       String val = (String) vars.get(key); 
    860       header = header.replaceAll("\\$\\{" + key + "\\}", val); 
    861     } 
    862     return header; 
    863   } 
    864  
    865   /** Gets overridden parameter name for the given version, if any. */ 
    866   private static String getParamName(String name, 
    867     String nodeName, String version) 
    868   { 
    869     String paramName = (String) 
    870       paramMap.get(version + ":" + nodeName + ":" + name); 
    871     return paramName == null ? name : paramName; 
    872   } 
    873  
    874   /** Gets last element of a node path. */ 
    875   private static String getLastPathElement(String path) { 
    876     int first = path.lastIndexOf("/") + 1; 
    877     return path.substring(first).replaceAll("[@\\!\\+]", ""); 
    878   } 
    879  
    880   // -- Helper classes -- 
    881  
    882   /** A helper class for storing information about a node. */ 
    883   private static class Node { 
    884     private String name, desc, extra; 
    885     private Hashtable paths = new Hashtable(); 
    886     private Vector indices; 
    887     private Vector params = new Vector(); 
    888   } 
    889  
    890   /** A helper class for storing information about node parameters. */ 
    891   private static class Param { 
    892     private String name, type, doc; 
    893     public String getArg(boolean doName, boolean doType, 
    894       boolean first, boolean last, String end) 
    895     { 
    896       StringBuffer sb = new StringBuffer(); 
    897       if (!first) sb.append(" "); 
    898       if (doType) sb.append(type); 
    899       if (doType && doName) sb.append(" "); 
    900       if (doName) sb.append(toVarName(stripPrefix(name))); 
    901       sb.append(last ? end : ","); 
    902       return sb.toString(); 
    903     } 
    904   } 
    905  
    906   /** A helper class for managing open output files. */ 
    907   public static class OutFiles { 
    908     private Hashtable files = new Hashtable(); 
    909     public void write(String id, String s) throws IOException { 
    910       getWriter(id).println(s); 
    911     } 
    912     public void closeFiles() throws IOException { 
    913       Enumeration e = files.keys(); 
    914       while (e.hasMoreElements()) { 
    915         String id = (String) e.nextElement(); 
    916         PrintWriter out = (PrintWriter) files.get(id); 
    917         writeFooter(id); 
    918         out.close(); 
    919       } 
    920       files.clear(); 
    921     } 
    922     private void openFile(String id) throws IOException { 
    923       PrintWriter out = new PrintWriter(new FileWriter(id)); 
    924       files.put(id, out); 
    925       writeHeader(id); 
    926     } 
    927     private PrintWriter getWriter(String id) throws IOException { 
    928       if (files.get(id) == null) openFile(id); 
    929       return (PrintWriter) files.get(id); 
    930     } 
     247    return entities; 
    931248  } 
    932249 
Note: See TracChangeset for help on using the changeset viewer.