Java tutorial
package org.apache.torque.map; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.io.Serializable; import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.StringTokenizer; import org.apache.commons.lang.StringUtils; import org.apache.torque.Database; import org.apache.torque.TorqueException; /** * DatabaseMap is used to model a database. * * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a> * @author <a href="mailto:dlr@collab.net">Daniel Rall</a> * @author <a href="mailto:greg.monroe@dukece.com">Greg Monroe</a> * @version $Id: DatabaseMap.java 1375888 2012-08-22 03:51:00Z tfischer $ */ public class DatabaseMap implements Serializable { /** * Serial version. */ private static final long serialVersionUID = 1L; /** * The character used by most implementations as the separator * between name elements. */ public static final char STD_SEPARATOR_CHAR = '_'; /** * The character which separates the schema name from the table name. */ public static final char SCHEMA_SEPARATOR_CHAR = '.'; /** * Format used to create create the class name for initializing a DB * specific map */ public static final String INIT_CLASS_NAME_FORMAT = "org.apache.torque.linkage.{0}DatabaseMapInit"; /** Error Message for class not found. */ private static final String ERROR_MESSAGES_CLASS_NOT_FOUND = "Invalid Torque OM setup for Database \"{0}\".\n" + "Database Map initialization class, \"{1}\"," + " " + "could not be found in your classpath."; /** Error Message for dependent class not found. */ private static final String ERROR_MESSAGES_DEPENDENT_CLASS_NOT_FOUND = "Invalid Torque OM setup for Database \"{0}\".\n" + "A class that the Database Map initialization class, \"{1}\", " + "depends on could not be found."; /** Error Message for class for name error. */ private static final String ERROR_MESSAGES_CLASS_FOR_NAME = "Invalid Torque OM setup for Database \"{0}\".\n" + "Something unexpected happened doing Class.forName(\"{1}\"). " + "See the nested exception for details."; /** Error Message for class for init error. */ private static final String ERROR_MESSAGES_INIT = "Invalid Torque OM setup for Database \"{0}\".\n" + "An error occured invoking the init() method in class, \"{1}\""; /** * The name of the database where this databaseMap belongs to, * for internal purposes only. */ private final String name; /** Name of the tables in the database. */ private final Map<String, TableMap> tables = Collections.synchronizedMap(new LinkedHashMap<String, TableMap>()); /** The id Table. */ private TableMap idTable = null; /** Flag indicating that all tables have been loaded via initialize() */ private boolean isInitialized = false; /** Associated options. */ private final Map<String, String> optionsMap = Collections.synchronizedMap(new LinkedHashMap<String, String>()); /** * Constructs a new DatabaseMap. */ public DatabaseMap(Database database) { if (database == null) { throw new NullPointerException("database must not be null"); } this.name = database.getName(); } /** * The name of the database to which this database map belongs. * * @return the database name, not null. */ String getName() { return name; } /** * Does this database contain this specific table? * * @param table The TableMap representation of the table. * @return True if the database contains the table. */ public boolean containsTable(TableMap table) { return containsTable(table.getName()); } /** * Does this database contain this specific table? * * @param name The String representation of the table. * @return True if the database contains the table. */ public boolean containsTable(String name) { if (name.indexOf('.') > 0) { name = name.substring(0, name.indexOf('.')); } boolean found = tables.containsKey(name); if (!found && idTable != null) { return idTable.getName().equals(name); } return found; } /** * Get a TableMap for the table by name. <p> * * Note that by default Torque uses lazy initialization to minimize * memory usage and startup time. However, if an OM or PEER class * has not called the table's MapBuilder class, it will not be here. * See the optional initialize method if you need full OM Mapping.<p> * * @param name Name of the table. * @return A TableMap, null if the table was not found. */ public TableMap getTable(String name) { TableMap result = tables.get(name); if (result != null) { return result; } if (idTable != null && idTable.getName().equals(name)) { return idTable; } return null; } /** * Get a TableMap[] of all of the tables in the database.<P> * * Note that by default Torque uses lazy initialization to minimize * memory usage and startup time. However, if an OM or PEER class * has not called the table's MapBuilder class, it will not be here. * See the optional initialize method if you need full OM Mapping.<p> * * @return A TableMap[]. */ public TableMap[] getTables() { int size = tables.size(); if (idTable != null) { size++; } TableMap[] dbTables = new TableMap[size]; synchronized (tables) { Iterator<TableMap> it = tables.values().iterator(); int i = 0; while (it.hasNext()) { dbTables[i++] = it.next(); } } if (idTable != null) { dbTables[size - 1] = idTable; } return dbTables; } /** * Add a new table to the database by name. It creates an empty * TableMap that you need to populate. * * @param tableName The name of the table. * * @return the new table map. */ public TableMap addTable(String tableName) { TableMap tmap = new TableMap(tableName, this); tables.put(tableName, tmap); return tmap; } /** * Add a new TableMap to the database. * * @param idTableMap The TableMap representation. */ public void setIdTable(TableMap idTableMap) { this.idTable = idTableMap; } /** * Returns an unmodifiable map of all options. * * @return A map containing all options, not null. */ public Map<String, String> getOptions() { return Collections.unmodifiableMap(optionsMap); } /** * Sets an option. * * @param key the key of the option * @param value the value of the option. */ public void setOption(String key, String value) { optionsMap.put(key, value); } /** * Returns the value of an option. * * @param key the key of the option. * * @return the value of the option, or null if not set. */ public String getOption(String key) { return optionsMap.get(key); } /** * Fully populate this DatabaseMap with all the TablesMaps. This * is only needed if the application needs to use the complete OM * mapping information. Otherwise, the OM Mapping information * will be populated as needed by OM and Peer classes. An example * of how to initialize the map info from the application:<p> * * <code> * DatabaseMap dbMap = Torque.getDatabaseMap( dbName ); * try { * dbMap.initialize(); * } catch ( TorqueException e ) { * ... error handling * } * </code> * * Note that Torque database names are case sensitive and this DB * map must be retrieved with the exact name used in the XML schema.<p> * * This uses Java reflection methods to locate and run the * init() method of a class generated in the org.apache.torque.linkage * package with a name based on the XML Database name value, e.g. * org.apache.torque.linkage.DefaultMapInit<p> * * Some misconfiguration situations that could cause this method to fail * are:<p> * * The class(es) in the org.apache.torque.linkage package were not included * with the other generated class files (e.g. the jar file creation process * only included com.* and not org.* files).<p> * * @throws TorqueException If an error is encountered locating and calling * the init method. */ public synchronized void initialize() throws TorqueException { if (isInitialized) { return; } String initClassName = MessageFormat.format(INIT_CLASS_NAME_FORMAT, new Object[] { javanameMethod(name) }); Class<?> initClass = null; try { initClass = Class.forName(initClassName); } catch (ClassNotFoundException e) { throw new TorqueException( MessageFormat.format(ERROR_MESSAGES_CLASS_NOT_FOUND, new Object[] { name, initClassName }), e); } catch (LinkageError e) { throw new TorqueException(MessageFormat.format(ERROR_MESSAGES_DEPENDENT_CLASS_NOT_FOUND, new Object[] { name, initClassName }), e); } catch (Throwable e) { throw new TorqueException( MessageFormat.format(ERROR_MESSAGES_CLASS_FOR_NAME, new Object[] { name, initClassName }), e); } try { Method initMethod = initClass.getMethod("init", (Class[]) null); initMethod.invoke(null, (Object[]) null); } catch (Exception e) { throw new TorqueException( MessageFormat.format(ERROR_MESSAGES_INIT, new Object[] { name, initClassName }), e); } isInitialized = true; } /** * Converts a database schema name to java object name. Operates * same as underscoreMethod but does not convert anything to * lowercase. This must match the javaNameMethod in the * JavaNameGenerator class in Generator code. * * @param schemaName name to be converted. * * @return converted name. */ protected String javanameMethod(String schemaName) { StringBuffer result = new StringBuffer(); StringTokenizer tok = new StringTokenizer(schemaName, String.valueOf(STD_SEPARATOR_CHAR)); while (tok.hasMoreTokens()) { String namePart = (String) tok.nextElement(); result.append(StringUtils.capitalize(namePart)); } // remove the SCHEMA_SEPARATOR_CHARs and capitalize // the tokens schemaName = result.toString(); result = new StringBuffer(); tok = new StringTokenizer(schemaName, String.valueOf(SCHEMA_SEPARATOR_CHAR)); while (tok.hasMoreTokens()) { String namePart = (String) tok.nextElement(); result.append(StringUtils.capitalize(namePart)); } return result.toString(); } /** * Copy all settings except the database from another database map. * * @param databaseMap the database map to copy from, not null. */ public void copyFrom(DatabaseMap databaseMap) { this.isInitialized = databaseMap.isInitialized; this.optionsMap.clear(); this.optionsMap.putAll(databaseMap.optionsMap); this.tables.clear(); this.tables.putAll(databaseMap.tables); } @Override public String toString() { StringBuilder result = new StringBuilder(); result.append("DatabaseMap[name=").append(name).append(", tables=("); boolean first = true; for (TableMap table : tables.values()) { if (!first) { result.append(','); } result.append(table.getName()); first = false; } result.append(")]"); return result.toString(); } }