001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.jdbc.schema;
020:
021: import java.sql.Types;
022:
023: import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
024: import org.apache.openjpa.jdbc.sql.DBDictionary;
025: import org.apache.openjpa.lib.conf.Configurable;
026: import org.apache.openjpa.lib.conf.Configuration;
027:
028: /**
029: * Factory whose schema group dynamically fills itself with information
030: * as mappings validate themselves in their <code>map</code> method.
031: * Tables are added when {@link SchemaGroup#findTable} is called. Columns
032: * are added to tables when {@link Table#getColumn} is called. And the
033: * column types are set when {@link Column#isCompatible} is called.
034: *
035: * @author Abe White
036: */
037: public class DynamicSchemaFactory extends SchemaGroup implements
038: SchemaFactory, Configurable {
039:
040: private transient DBDictionary _dict = null;
041: private String _schema = null;
042:
043: public void setConfiguration(Configuration conf) {
044: JDBCConfiguration jconf = (JDBCConfiguration) conf;
045: _dict = jconf.getDBDictionaryInstance();
046: _schema = jconf.getSchema();
047: }
048:
049: public void startConfiguration() {
050: }
051:
052: public void endConfiguration() {
053: }
054:
055: public SchemaGroup readSchema() {
056: return this ;
057: }
058:
059: public void storeSchema(SchemaGroup schema) {
060: // nothing to do
061: }
062:
063: public boolean isKnownTable(Table table) {
064: return super .findTable(table) != null;
065: }
066:
067: public boolean isKnownTable(String name) {
068: return super .findTable(name) != null;
069: }
070:
071: public Table findTable(String name) {
072: if (name == null)
073: return null;
074:
075: Table table = super .findTable(name);
076: if (table != null)
077: return table;
078:
079: // if full name, split
080: String schemaName = null;
081: String tableName = name;
082: int dotIdx = name.lastIndexOf('.');
083: if (dotIdx != -1) {
084: schemaName = name.substring(0, dotIdx);
085: tableName = name.substring(dotIdx + 1);
086: } else
087: schemaName = _schema;
088:
089: Schema schema = getSchema(schemaName);
090: if (schema == null)
091: schema = addSchema(schemaName);
092: return schema.addTable(tableName);
093: }
094:
095: protected Table newTable(String name, Schema schema) {
096: return new DynamicTable(name, schema);
097: }
098:
099: protected Column newColumn(String name, Table table) {
100: return new DynamicColumn(name, table);
101: }
102:
103: /**
104: * Table type that adds columns when {@link #getColumn} is called.
105: */
106: private static class DynamicTable extends Table {
107:
108: public DynamicTable(String name, Schema schema) {
109: super (name, schema);
110: }
111:
112: public Column getColumn(String name) {
113: if (name == null)
114: return null;
115:
116: Column col = super .getColumn(name);
117: if (col != null)
118: return col;
119: return addColumn(name);
120: }
121: }
122:
123: /**
124: * Column type that sets its type when {@link #isCompatible} is called.
125: */
126: private class DynamicColumn extends Column {
127:
128: public DynamicColumn(String name, Table table) {
129: super (name, table);
130: }
131:
132: public boolean isCompatible(int type, String typeName,
133: int size, int decimals) {
134: if (getType() != Types.OTHER)
135: return super .isCompatible(type, typeName, size,
136: decimals);
137:
138: if (type == Types.VARCHAR && size <= 0)
139: size = _dict.characterColumnSize;
140: setType(type);
141: setSize(size);
142: if (typeName != null)
143: setTypeName(typeName);
144: if (decimals >= 0)
145: setDecimalDigits(decimals);
146: return true;
147: }
148: }
149: }
|