Package org.xorm

Source Code of org.xorm.ModelMapping

/*
    $Header: /cvsroot/xorm/xorm/src/org/xorm/ModelMapping.java,v 1.57 2004/05/04 18:57:09 wbiggs Exp $

    This file is part of XORM.

    XORM 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.

    XORM 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 XORM; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package org.xorm;

import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import javax.jdo.JDOFatalException;
import javax.jdo.JDOFatalUserException;
import javax.jdo.JDOUserException;
import javax.jdo.spi.JDOImplHelper;
import javax.jdo.spi.PersistenceCapable;
import javax.sql.DataSource;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

import org.xorm.datastore.Column;
import org.xorm.datastore.ConnectionInfo;
import org.xorm.datastore.Table;
import org.xorm.datastore.sql.SQLConnectionInfo;
import org.xorm.datastore.sql.SQLType;
import org.xorm.util.FieldDescriptor;
import org.xorm.util.jdoxml.*;

/**
* Represents the full set of mappings for an object model.
*/
public class ModelMapping implements Configurable, I15d {
    protected static Logger logger = Logger.getLogger("org.xorm.ModelMapping");
   
    public static final String XORM_VENDOR_NAME = "XORM";

    public static final String ATTR_SOURCE = "source";
    public static final String ATTR_TARGET = "target";
    public static final String ATTR_ORDER_BY = "order-by";
    public static final String ATTR_INDEX = "index";
    public static final String ATTR_FILTER = "filter";
    public static final String ATTR_PARAMETERS = "parameters";
    public static final String ATTR_VARIABLES = "variables";
    public static final String ATTR_ORDERING = "ordering";
    public static final String ATTR_IMPORTS = "imports";

    public static final String DATABASE_XML = "org.xorm.datastore.database";
    public static final String DATABASE_DTD = "/org/xorm/datastore/database.dtd";

    public static final String OPTION_VALIDATE_XML = "org.xorm.option.ValidateXML";
    public static final String OPTION_BOOTSTRAP_JDO = "org.xorm.option.BootstrapJDO";
    public static final String OPTION_DEFAULT_MAPPING = "org.xorm.option.DefaultMapping";
    public static final String OPTION_ONLY_CONFIGURED_PROPERTIES = "org.xorm.option.onlyConfiguredProperties";

    private HashMap classToMapping = new HashMap();
    private HashMap nameToTable = new HashMap();
    private Properties properties;
    private InterfaceManagerFactory factory;
    private boolean validateXML = true;
    private boolean useDefaultMapping = false;
    private boolean registerClasses = false;
    private boolean usingDatabaseMetaData = false;

    public void setFactory(InterfaceManagerFactory factory) {
        this.factory = factory;
    }

    public void addClassMapping(ClassMapping mapping) {
        Class clazz = mapping.getMappedClass();
        // System.out.println("Registering class: " + clazz.getName());
        classToMapping.put(clazz, mapping);

        if (registerClasses) {
            // Register XORM-specific classes' JDO Metadata
     
            if (!PersistenceCapable.class.isAssignableFrom(clazz)) {
                InterfaceInvocationHandler handler = new InterfaceInvocationHandler(factory, mapping, null);
                PersistenceCapable pc = (PersistenceCapable) handler.newProxy();
   
                Collection managedFields = mapping.getManagedFields();
                int len = managedFields.size();
                String[] fieldNames = new String[len];
                Class[] fieldTypes = new Class[len];
                byte[] fieldFlags = new byte[len];
                int i = 0;
                Iterator it = managedFields.iterator();
                while (it.hasNext()) {
                    FieldDescriptor fd = mapping.getFieldDescriptor
                        ((String) it.next());
                    fieldNames[i] = fd.name;
                    fieldTypes[i] = fd.type;
                    fieldFlags[i] = (byte) (pc.CHECK_READ | pc.CHECK_WRITE);
                    i++;
                }
   
                // Register it with JDOImplHelper
                JDOImplHelper.registerClass(clazz,
                                            fieldNames,
                                            fieldTypes,
                                            fieldFlags,
                                            null, // PC superclasses not supported
                                            pc);
            }
        }
    }

    /**
     * Retrieves a ClassMapping for the specified class.  If the class
     * itself is not mapped, but a superclass or superinterface is mapped,
     * that mapping is cloned and used for the specified class.
     * @exception JDOUserException if no applicable mapping is found
     */
    public ClassMapping getClassMapping(Class clazz) {
        ClassMapping mapping = getClassMappingImpl(clazz);
        if (mapping == null) {
            throw new JDOUserException(I18N.msg("E_no_class_mapping", clazz.getName()));
        }
        return mapping;
    }

    private ClassMapping getClassMappingImpl(Class clazz) {
        // First check the cache of previously loaded mappings
        if (classToMapping.containsKey(clazz)) {
            return (ClassMapping) classToMapping.get(clazz);
        }
        ClassMapping mapping;
        if ((mapping = loadClassMapping(clazz)) == null) {
            boolean found = false;
            Class[] interfaces = clazz.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                if ((mapping = getClassMappingImpl(interfaces[i])) != null) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                /*             
                                if(!clazz.isInterface()){
                                //try superclass
                                */
                Class superclass = clazz.getSuperclass();
                if ((superclass != null) && ((mapping = getClassMappingImpl(superclass)) != null)) {
                    found = true;
                }
                /*
              } else {
                //try to find class implementing this iterface, first found will be used
                logger.info("loking for implementation for interface "+clazz);
                Iterator classesIter = classToMapping.keySet().iterator();
                while (classesIter.hasNext()) {
                  Class nextClass = (Class) classesIter.next();
                  if(clazz.isAssignableFrom(nextClass)){
                    logger.info("found matching class "+nextClass);
                    mapping = (ClassMapping)classToMapping.get(nextClass);
                    found = true;
                    break;
                  }
                }
              }
                */
            }
            if (found && !mapping.getMappedClass().equals(clazz)) {
                // Simulate the mapping
                //System.out.println("Cloning ClassMapping for " + mapping.getMappedClass() + " to " + clazz);
                mapping = (ClassMapping) mapping.clone();
                mapping.clazz = clazz;
                addClassMapping(mapping);
                //classToMapping.put(clazz, mapping);
            }
        }
        return mapping;
    }

    /**
     * Loads the class mapping information by reading the corresponding
     * JDO metadata files.
     *
     * @param clazz the interface or abstract class class to be loaded
     * @return a ClassMapping object representing the mappings, or
     *   null if no mapping exists.
     */
    private synchronized ClassMapping loadClassMapping(Class clazz) {
        // First request for this class; read appropriate JDO files.
        String name = clazz.getName();
        StringTokenizer toke = new StringTokenizer(name, ".");
        StringBuffer path = new StringBuffer("/");
        while (toke.hasMoreTokens()) {
            path.append(toke.nextToken());
            if (toke.hasMoreTokens()) {
                path.append("/");
            } else {
                path.append(".jdo");
            }
        }
        InputStream jdo = getClass().getResourceAsStream(path.toString());
        if (jdo == null) {
            // Try package file
            int pos = path.toString().lastIndexOf("/");
            if (pos > 0) {
                path.delete(pos, path.length());
                path.append(".jdo");
            }
            jdo = getClass().getResourceAsStream(path.toString());
        }
        if (jdo == null) {
            // No mapping exists
            classToMapping.put(clazz, null);
            return null;
        } else {
            initJDO(jdo);
            return (ClassMapping) classToMapping.get(clazz);
        }
    }

    public Table getTable(String name) {
        return (Table) nameToTable.get(name);
    }

    /**
     * Initializes an empty ModelMapping that will be populated
     * on demand by reading JDO files, or can be hand-populated
     * by the user.
     * @param props the Properties to use
     */
    public void setProperties(Properties props) {
        this.properties = props;

        validateXML = !"false".equalsIgnoreCase(properties.getProperty(OPTION_VALIDATE_XML));
        useDefaultMapping = "true".equalsIgnoreCase(properties.getProperty(OPTION_DEFAULT_MAPPING));
       
        String databaseXML = properties.getProperty(DATABASE_XML);
        if (databaseXML != null) {
            SAXBuilder biff = new SAXBuilder(validateXML);
            biff.setEntityResolver(new EntityResolver() {
                    public InputSource resolveEntity(String publicId, String systemId) {
                        if ("database.dtd".equals(systemId)) {
                            return new InputSource(getClass().getResourceAsStream(DATABASE_DTD));
                        }
                        return null;
                    }
                });
            InputStream testStream = getClass().getResourceAsStream(databaseXML);
            if(testStream == null){
              testStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(databaseXML);
            }
            if(testStream == null) {
                throw new JDOFatalUserException(I18N.msg("E_locate_db_xml", databaseXML))
            }
            InputSource inputSource = new InputSource(testStream);

            // Fake out Crimson
            inputSource.setSystemId(getClass().getResource(DATABASE_DTD).toString());

            try {
                Document doc = biff.build(inputSource);
                Element root = doc.getRootElement();
                parseTables(root);
            } catch (JDOMException e) {
                throw new JDOFatalException(I18N.msg("E_parse_db_xml", databaseXML), e);
            } catch (IOException e) {
                throw new JDOFatalException(I18N.msg("E_parse_db_xml", databaseXML), e);
            }
        }
        else {
            // DATABASE_XML was not defined.
            usingDatabaseMetaData = true;
            logger.info(DATABASE_XML +
                        " not defined, will dynamically use DatabaseMetaData");
        }
 
        // Check for bootstrap loading of JDO files
        String bootstrap = properties.getProperty(OPTION_BOOTSTRAP_JDO);
        if (bootstrap != null) {
            String[] parts = bootstrap.split(",");
            registerClasses = true;
            for (int i = 0; i < parts.length; i++) {
                InputStream jdo = getClass().getResourceAsStream(parts[i]);
                initJDO(jdo);
            }
            registerClasses = false;
        }
    }

    /**
     * Returns true if the interface type passed in has been configured
     * via the mapping file to be persisted.
     * Note that this is NOT the same thing as checking if an instance
     * that implements the interface is managed, and in particular, a call to
     * mgr.isManagedType(persistentInstance.getClass())
     * will NOT return true.
     */
    public boolean isManagedType(Class type) {
        return (getClassMappingImpl(type) != null);
    }

    /** Used as a utility method from init. */
    private String getPackagedClassName(String className, String defaultPackage) {
        if (defaultPackage == null || className.indexOf('.') != -1) {
            return className;
        }
        return defaultPackage + '.' + className;
    }

    /**
     * Uses JDOM to load configuration from an XML .jdo file.
     */
    private void initJDO(InputStream mappingStream) {
        try {
            JDOPackage jdoPackage = JDOXML.read(mappingStream, validateXML);
            String defaultPackage = jdoPackage.getName();
            if ("".equals(defaultPackage)) {
                defaultPackage = null;
            }

            if (usingDatabaseMetaData) {
                // The user didn't specify a DATABASE_XML file, so we need
                // to load all tables referenced in the .jdo file from the
                // database.
                loadReferencedTablesFromMetaData(jdoPackage);
            }

            // Look at the classes twice: first create ClassMapping
            // instances with tables only, then fill in the details.
            // This is done so that different ClassMappings can use
            // each other's default fetch group settings, possibly
            // circularly.
            Iterator i = jdoPackage.getClasses().iterator();
            while (i.hasNext()) {
                JDOClass jdoClass = (JDOClass) i.next();
                String className = getPackagedClassName(jdoClass.getName(), defaultPackage);
                Class c = Class.forName(className);
                ClassMapping classMapping;
                if("true".equalsIgnoreCase(properties.getProperty(OPTION_ONLY_CONFIGURED_PROPERTIES))) {
                    classMapping = new ClassMapping(this, c, jdoClass);
                } else {
                    classMapping = new ClassMapping(this, c);
                }

                Iterator exts = jdoClass.getExtensions().iterator();
                JDOExtension extension;
                Class dsi = null;
                Table t = null;
                while (exts.hasNext()) {
                    extension = (JDOExtension) exts.next();
                    if (XORM_VENDOR_NAME.equals(extension.getVendorName())) {
                        String key = extension.getKey();
                        if ("datastore-identity-type".equals(key)) {
                            dsi = Class.forName(extension.getValue());
                        } else if ("table".equals(key)) {
                            String tableName = extension.getValue();
                            t = getTable(tableName);
                            if (t == null) {
                                throw new JDOFatalUserException(I18N.msg("E_no_table_definition", tableName));
                            }
                        }
                    }
                }
   
                if (t == null && !useDefaultMapping) {
                    throw new JDOFatalUserException(I18N.msg("E_no_table", c.getName()));
                }

                classMapping.setTable(t);
                classMapping.setDatastoreIdentityType(dsi);
                addClassMapping(classMapping);
            }
            i = jdoPackage.getClasses().iterator();
            while (i.hasNext()) {
                JDOClass jdoClass = (JDOClass) i.next();
                parseClass(jdoClass, defaultPackage);
            }

        } catch (IOException e) {
            throw new JDOFatalException(I18N.msg("E_parse_jdo_xml"), e);
        } catch (ClassNotFoundException e) {
            throw new JDOFatalException(I18N.msg("E_jdo_xml_no_class", e.getMessage()));
        }
    }

    /**
     * Parses a <class> element passed in as the first parameter.
     */
    private void parseClass(JDOClass jdoClass, String defaultPackage) throws ClassNotFoundException {
        String className = getPackagedClassName(jdoClass.getName(), defaultPackage);
        Class c = Class.forName(className);
        ClassMapping classMapping = getClassMapping(c);
        Table t = classMapping.getTable();
 
        Iterator exts;
        JDOExtension extension;
        // read fields
        Iterator j = jdoClass.getFields().iterator();
        while (j.hasNext()) {
            JDOField field = (JDOField) j.next();
            exts = field.getExtensions().iterator();
            while (exts.hasNext()) {
                extension = (JDOExtension) exts.next();
                if (XORM_VENDOR_NAME.equals(extension.getVendorName())) {
                    String key = extension.getKey();
                    if ("column".equals(key)) {
                        Column c2 = t.getColumnByName(extension.getValue());
                        if (c2 == null) {
                            throw new JDOFatalUserException(I18N.msg("E_no_column", extension.getValue(), t.getName(), jdoClass.getName()));
                        }
                        classMapping.setColumn(field.getName(), c2, field.isDefaultFetchGroup());
                        if (field.getNullValue().equals(JDONullValue.EXCEPTION)) {
                            // TODO: should this be done here?
                            c2.setNonNull(true);
                        }
                    } else if ("inverse".equals(key)) {
                        classMapping.setInverse(field.getName(), extension.getValue());
                    }
                } // XORM is vendor-name
            } // end extension elements
            // See if field is a collection
            JDOCollection collection = field.getCollection();
            if (collection != null) {
                RelationshipMapping rm = parseRelationship(collection, c, defaultPackage, field, jdoClass);
                classMapping.setRelationship(field.getName(), rm);
            }
        }
    }

    private RelationshipMapping parseRelationship(JDOCollection root, Class ownerClass, String defaultPackage, JDOField field, JDOClass jdoClass) throws ClassNotFoundException {
        RelationshipMapping relationship = new RelationshipMapping();
        String elementType = root.getElementType();
        elementType = getPackagedClassName(elementType, defaultPackage);

        Class elementClass = Class.forName(elementType);
       
        RelationshipMapping.Endpoint source = new RelationshipMapping.Endpoint();
        source.setCollectionType(source.SET);
        source.setElementClass(elementClass);
        relationship.setSource(source);

        RelationshipMapping.Endpoint target = new RelationshipMapping.Endpoint();
        target.setCollectionType(target.SET);
        relationship.setTarget(target);

        Table table = null;
        Iterator i = root.getExtensions().iterator();
        String sourceStr = null;
        String targetStr = null;
        String indexStr = null;
        // Added support for filtered collections (Dan Checkoway, 6/26/03)
        String filterStr = null;
        String parametersStr = null;
        String variablesStr = null;
        String importsStr = null;
        while (i.hasNext()) {
            JDOExtension element = (JDOExtension) i.next();
            if (XORM_VENDOR_NAME.equals(element.getVendorName())) {
                String key = element.getKey();
                String value = element.getValue();
                boolean redefined = false;
                if ("table".equals(key)) {
                    redefined = table != null;
                    table = getTable(value);
                    if (table == null) {
                        throw new JDOFatalUserException(I18N.msg("E_unknown_table", value));
                    }
                } else if (ATTR_SOURCE.equals(key)) {
                    redefined = sourceStr != null;
                    sourceStr = value;
                } else if (ATTR_TARGET.equals(key)) {
                    redefined = targetStr != null;
                    targetStr = value;
                } else if (ATTR_ORDER_BY.equals(key)) {
                    redefined = relationship.getOrderBy() != null;
                    relationship.setOrderBy(value);
                } else if (ATTR_INDEX.equals(key)) {
                    redefined = indexStr != null;
                    indexStr = value;
                } else if (ATTR_FILTER.equals(key)) {
                    // Filtered collection query
                    redefined = filterStr != null;
                    filterStr = value;
                } else if (ATTR_PARAMETERS.equals(key)) {
                    // Filtered collection query parameters
                    redefined = parametersStr != null;
                    parametersStr = value;
                } else if (ATTR_VARIABLES.equals(key)) {
                    // Filtered collection query variables
                    redefined = variablesStr != null;
                    variablesStr = value;
                } else if (ATTR_ORDERING.equals(key)) {
                    // JDO-style ordering
                    redefined = relationship.getOrdering() != null;
                    relationship.setOrdering(value);
                } else if (ATTR_IMPORTS.equals(key)) {
                    redefined = importsStr != null;
                    importsStr = value;
                }
                if (redefined) {
                    throw new JDOFatalUserException(I18N.msg("E_collection_redefinition", key, field.getName(), jdoClass.getName()));
                }
            }
        } // for each "extension" element

        if (sourceStr == null && filterStr == null) {
            if (useDefaultMapping) {
                sourceStr = "source_" + ownerClass.getName();
            } else {
                // You have to specify either a source or a filter or both.
                throw new JDOFatalUserException(I18N.msg("E_collection_no_source", field.getName(), jdoClass.getName()));
            }
        }
       
        if (table == null) {
            // The table wasn't explicitly specified.  We can safely
            // assume that if a collection is specified without an explicit
            // table, then the table is the collection element type's table.
            ClassMapping mapping = getClassMapping(elementClass);
            if ((table = mapping.getTable()) == null) {
                // Not much we can do about this.  I don't think it will ever
                // happen, but just in case...
                throw new JDOFatalUserException(I18N.msg("E_collection_no_table", field.getName(), jdoClass.getName()));
            }
            logger.fine("No table specified for collection field \"" +
                        field.getName() +
                        "\"...assuming element type table: " +
                        table.getName());
        }

        if (relationship.getOrderBy() != null &&
            relationship.getOrdering() != null) {
            // Don't even bother trying to interpret precedence
            throw new JDOFatalUserException(I18N.msg("E_collection_order_by_and_ordering"));
        }

        if (relationship.getOrdering() != null && filterStr == null) {
            throw new JDOFatalUserException(I18N.msg("E_collection_ordering_without_filter", field.getName(), jdoClass.getName()));
        }
       
        if (sourceStr != null) {
            source.setColumn(table.getColumnByName(sourceStr));
        }

        if (targetStr == null) {
            target.setColumn(table.getPrimaryKey());
        } else {
            // It's many-to-many.  We used to set the target's elementClass
            // to signify this, but that seemed like a hack to me.  And since
            // the target's elementClass was set to the owner class, which
            // didn't seem to apply (if anything the target element class
            // would be the collection's element class, not the owner's class),
            // I added this boolean setter/getter instead.
            relationship.setMToN(true);
            target.setColumn(table.getColumnByName(targetStr));
        }

        if (indexStr != null) {
            Column c = table.getColumnByName(indexStr);
            // Set the column to managed mode; we don't want
            // indices to be included in Row.equals() operations
            c.setManaged(true);
            relationship.setIndexColumn(c);
        }

        if (filterStr != null && !filterStr.equals("")) {
            relationship.setFilter(filterStr);
            // Only set parameters & variables if the filter is specified.
            // Otherwise it would make no sense.
            if (parametersStr != null && !parametersStr.equals("")) {
                relationship.setParameters(parametersStr);
            }
            if (variablesStr != null && !variablesStr.equals("")) {
                relationship.setVariables(variablesStr);
            }
            if (importsStr != null && !importsStr.equals("")) {
                relationship.setImports(importsStr);
            }
        }
       
        return relationship;
    }

    private void parseTables(Element root) {
        List tables = root.getChildren("table");
        Iterator i = tables.iterator();
        while (i.hasNext()) {
            Element element = (Element) i.next();
            String tableName = element.getAttributeValue("name");
            Table table = new Table(tableName);
            nameToTable.put(tableName, table);
            List columns = element.getChildren("column");
            Iterator j = columns.iterator();
            while (j.hasNext()) {
                Element colElement = (Element) j.next();
                Column column = new Column(table, colElement.getAttributeValue("name"));
                if ("true".equalsIgnoreCase(colElement.getAttributeValue("primary-key"))) {
                    table.setPrimaryKey(column);
                }
                if ("true".equalsIgnoreCase(colElement.getAttributeValue("read-only"))) {
                    column.setReadOnly(true);
                }
                if ("true".equalsIgnoreCase(colElement.getAttributeValue("non-null"))) {
                    column.setNonNull(true);
                }
                // Is it a sequenced column?
                if (colElement.getAttributeValue("sequence") != null) {
                    column.setSequence(colElement.getAttributeValue("sequence"));
                }
                // Is it an autoincremented column?
                if ("true".equalsIgnoreCase(colElement.getAttributeValue("auto"))) {
                    column.setAutoIncremented(true);
                }
                // Is it manually typed?
                column.setType(colElement.getAttributeValue("type"));
                column.setFormat(colElement.getAttributeValue("format"));
            } // columns iterator
            // map the table for later reference
        } // tables iterator
    }

    /**
     * Generates a list of table names extracted from the JDO file
     * and passes each one to ConnectionInfo.describeTable(String name).
     */
    private void loadReferencedTablesFromMetaData(JDOPackage jdoPackage)
    {
        HashSet tableNames = new HashSet();
        for (Iterator classIter = jdoPackage.getClasses().iterator();
             classIter.hasNext(); ) {
            JDOClass jdoClass = (JDOClass)classIter.next();
            // Look at the class extensions for the "table"
            for (Iterator extIter = jdoClass.getExtensions().iterator();
                 extIter.hasNext(); ) {
                JDOExtension extension = (JDOExtension)extIter.next();
                if ("table".equals(extension.getKey())) {
                    String tableName = extension.getValue();
                    if (tableNames.add(tableName)) {
                        logger.fine("Discovered table name: " + tableName);
                    }
                }
            }
            // Look at the class fields and everything under there
            for (Iterator fieldIter = jdoClass.getFields().iterator();
                 fieldIter.hasNext(); ) {
                JDOField field = (JDOField)fieldIter.next();
                // Look at the field's extensions
                for (Iterator extIter = field.getExtensions().iterator();
                     extIter.hasNext(); ) {
                    JDOExtension extension = (JDOExtension)extIter.next();
                    if ("table".equals(extension.getKey())) {
                        String tableName = extension.getValue();
                        if (tableNames.add(tableName)) {
                            logger.fine("Discovered table name: " + tableName);
                        }
                    }
                }

                // Look at the field's collection, if there is one
                JDOCollection collection = field.getCollection();
                if (collection != null) {
                    for (Iterator extIter = collection.getExtensions().iterator();
                         extIter.hasNext(); ) {
                        JDOExtension extension = (JDOExtension)extIter.next();
                        if ("table".equals(extension.getKey())) {
                            String tableName = extension.getValue();
                            if (tableNames.add(tableName)) {
                                logger.fine("Discovered table name: " + tableName);
                            }
                        }
                    }
                }
            }
        }

        logger.fine("Discovered " + tableNames.size() +
                    " table names...loading them now");

        ConnectionInfo ci = factory.getConnectionInfo();
        for (Iterator iter = tableNames.iterator(); iter.hasNext(); ) {
            String tableName = (String)iter.next();
            // Load it from db metadata
            nameToTable.put(tableName, ci.describeTable(tableName));
        }
    }
}
TOP

Related Classes of org.xorm.ModelMapping

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.