// // MetaEntityList.java // /* Bio-Formats autogen package for programmatically generating source code. Copyright (C) 2005-@year@ UW-Madison LOCI and Glencoe Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.StringTokenizer; import java.util.Vector; /** * An entity list for the OME data model. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/autogen/src/MetaEntityList.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/autogen/src/MetaEntityList.java;hb=HEAD">Gitweb</a></dd></dl> * * @author Curtis Rueden ctrueden at wisc.edu */ public class MetaEntityList extends EntityList { // -- Constants -- /** Path to versions definition file. */ public static final String VERSION_SRC = "versions.txt"; /** Path to entities definition file. */ public static final String ENTITY_SRC = "entities.txt"; // -- Constructors -- /** Constructs an entity list for the OME data model. */ public MetaEntityList() throws IOException { super(VERSION_SRC, ENTITY_SRC); } // -- MetaEntityList API methods - versions -- public String className() { return value("className"); } public String id() { return value("id"); } public String basePackage() { return value("basePackage"); } public String version() { return value("version"); } public boolean spwImport() { return !"false".equals(value("spwImport")); } // -- MetaEntityList API methods - entities -- /** Whether the entity can appear multiple times. */ public boolean countable() { return "true".equals(value("countable")); } public String path() { return value("path"); } public String defaultPath() { return value("path", null, ent, prop); } /** List of nodes in the path, with markup symbols. Derived from path. */ public String[] pathNodes() { return path().split("\\/"); } /** Last node in the path, without markup symbols. Derived from path. */ public String last() { return last(path()); } /** Path without its last <em>countable</em> node. Derived from path. */ public String chop() { return chop(path()); } /** List of indices in the path. Derived from path. */ public Vector<String> indices() { return indices(path()); } /** List of method arguments for the path indices. Derived from path. */ public String argsList() { return argsList(defaultPath()); } /** List of types for the path indices. Derived from path. */ public String typesList() { return typesList(defaultPath()); } /** List of variables for the path indices. Derived from path. */ public String varsList() { return varsList(path(), defaultPath()); } /** * List of distinct path values for the active version, including sub-paths. * Derived from path values of all entities and properties. */ public Vector<String> unique() { HashSet<String> set = new HashSet<String>(); Vector<String> unique = new Vector<String>(); for (String entity : entities.keySet()) { Entity e = entities.get(entity); for (String property : e.props.keySet()) { String path = value("path", ver, entity, property); if (path.equals("-")) continue; while (true) { if (set.contains(path)) break; // already processed this path set.add(path); unique.add(path); int slash = path.lastIndexOf("/"); if (slash < 0) break; path = path.substring(0, slash); } } } Collections.sort(unique); return unique; } // -- MetaEntityList API methods - properties -- public String type() { return value("type"); } public String defaultType() { return value("type", null, ent, prop); } public String getter(String nodeVar) { String getter = value("getter"); String s = getter == null ? "get" + name() : getter; s = nodeVar + "." + s; // inject conversion method if needed String type = type(); String defaultType = defaultType(); if (type.equals(defaultType)) s = s + "()"; else s = var(type) + "To" + defaultType + "(" + s + "())"; return s; } public String setter(String nodeVar, String value) { String setter = value("setter"); String s = setter == null ? "set" + name() : setter; // inject conversion method if needed String type = type(); String defaultType = defaultType(); if (type.equals(defaultType)) s = s + "(" + value + ")"; else s = s + "(" + var(defaultType) + "To" + type + "(" + value + "))"; return nodeVar + "." + s; } public String enumeration() { return value("enumeration"); } public String defaultValue() { return value("defaultValue"); } // -- MetaEntityList API methods - entities/properties -- public String description() { return value("description"); } public String notes() { return value("notes"); } /** Synthesized combination of description and notes. */ public String doc() { StringBuffer sb = new StringBuffer(); sb.append(description()); sb.append("."); String notes = notes(); if (notes != null) { sb.append(" "); sb.append(notes); } return sb.toString(); } // -- MetaEntityList API methods - other -- // NB: These methods could be static, but are instance methods // to make it easier for Velocity templates to reference them. /** Converts name in CamelCase to variable in variableCase. */ public String var(String s) { char[] c = s.toCharArray(); for (int i=0; i<c.length; i++) { if (c[i] >= 'A' && c[i] <= 'Z') c[i] += 'a' - 'A'; else { if (i > 1) c[i - 1] += 'A' - 'a'; // keep last character capitalized break; } } return new String(c).replaceAll("[^\\w]", ""); } /** Converts the given type from Java to Slice syntax. */ public String ice(String s) { s = s.toLowerCase(); s = s.replaceAll("\\[\\]", "Seq"); s = s.replaceAll("integer", "int"); s = s.replaceAll("boolean", "bool"); if (s.endsWith("Seq")) { // capitalize first letter char[] c = s.toCharArray(); if (c[0] >= 'a' && c[0] <= 'z') c[0] += 'A' - 'a'; s = new String(c); } return s; } /** Converts the given wrapper class name to the equivalent primitive. */ public String primitive(String s) { if (s.equals("Boolean")) return "boolean"; if (s.equals("Character")) return "char"; if (s.equals("Byte")) return "byte"; if (s.equals("Double")) return "double"; if (s.equals("Float")) return "float"; if (s.equals("Integer")) return "int"; if (s.equals("Long")) return "long"; if (s.equals("Short")) return "short"; return s; } /** Gets the last node in the given path, without markup symbols. */ public String last(String path) { int first = path.lastIndexOf("/") + 1; return path.substring(first).replaceAll("\\+", ""); } /** Gets a path without its last <em>countable</em> node. */ public String chop(String path) { int plus = path.lastIndexOf("+"); if (plus < 0) return null; int slash = path.lastIndexOf("/", plus); return slash < 0 ? "" : path.substring(0, slash); } /** List of indices in the given path. */ public Vector<String> indices(String path) { Vector<String> list = new Vector<String>(); StringTokenizer st = new StringTokenizer(path, "/"); int tokens = st.countTokens(); for (int i=0; i<tokens; i++) { String t = st.nextToken(); if (t.endsWith("+")) list.add(t.replaceAll("\\+", "")); } return list; } /** * Gets a list of method arguments for the indices in the given path. * E.g., "int imageIndex, int pixelsIndex, int planeIndex". */ public String argsList(String path) { return indicesList(path, path, true, true); } /** * Gets a list of types for the indices in the given path. * E.g., "int, int, int". */ public String typesList(String path) { return indicesList(path, path, true, false); } /** * Gets a list of variables for the indices in the given path. * E.g., "imageIndex, pixelsIndex, planeIndex". */ public String varsList(String path) { return varsList(path, path); } /** * Gets a list of variables for the indices in the given path. * E.g., "imageIndex, pixelsIndex, planeIndex". */ public String varsList(String path, String defaultPath) { return indicesList(path, defaultPath, false, true); } private String indicesList(String path, String defaultPath, boolean doTypes, boolean doVars) { StringBuffer sb = new StringBuffer(); Vector<String> indices = indices(path); Vector<String> defaultIndices = indices(defaultPath); while (defaultIndices.size() > indices.size()) { defaultIndices.remove(defaultIndices.size() - 1); } boolean first = true; for (String index : defaultIndices) { if (first) first = false; else sb.append(", "); if (doTypes) sb.append("int"); if (doTypes && doVars) sb.append(" "); if (doVars) sb.append(var(index + "Index")); } return sb.toString(); } }