001: /**
002: * Objective Database Abstraction Layer (ODAL)
003: * Copyright (c) 2004, The ODAL Development Group
004: * All rights reserved.
005: * For definition of the ODAL Development Group please refer to LICENCE.txt file
006: *
007: * Distributable under LGPL license.
008: * See terms of license at gnu.org.
009: */package com.completex.objective.components.persistency.meta;
010:
011: import com.completex.objective.components.persistency.MetaTable;
012: import com.completex.objective.components.persistency.ModelConsts;
013: import com.completex.objective.components.persistency.UserDefinedTypeMetaModel;
014: import com.completex.objective.components.persistency.DescriptorMappable;
015:
016: import java.util.ArrayList;
017: import java.util.Collection;
018: import java.util.Iterator;
019: import java.util.LinkedHashMap;
020: import java.util.List;
021: import java.util.Map;
022: import java.util.StringTokenizer;
023: import java.util.regex.Pattern;
024: import java.util.regex.Matcher;
025:
026: /**
027: * @author Gennady Krizhevsky
028: */
029: public class MetaModel implements ModelConsts, DescriptorMappable {
030:
031: private Map tables = new LinkedHashMap(); // Map<MetaTable>
032: private UserDefinedTypeMetaModel userDefinedTypeMetaModel;
033:
034: private ModelFilter filter = ModelFilter.NULL_MODEL_FILTER;
035:
036: public MetaModel() {
037: }
038:
039: public MetaModel(String filterPattern) {
040: if (filterPattern != null && filterPattern.trim().length() > 0) {
041: if (RegExpModelFilter.isRegExp(filterPattern)) {
042: this .filter = new RegExpModelFilter(filterPattern);
043: } else {
044: this .filter = new DefaultModelFilter(filterPattern);
045: }
046: }
047: }
048:
049: public ModelFilter getFilter() {
050: return filter;
051: }
052:
053: public MetaTable getTable(String tableKey) {
054: return (MetaTable) tables.get(tableKey);
055: }
056:
057: public boolean isTableAllowed(String tableName) {
058: return filter.isAllowed(tableName);
059: }
060:
061: public MetaTable addTable(String tableName) {
062: if (tableName == null) {
063: throw new IllegalArgumentException("tableName == null");
064: }
065: MetaTable table = null;
066: if (filter.isAllowed(tableName)) {
067: table = (MetaTable) tables.get(tableName);
068: if (table == null) {
069: table = new MetaTable(tableName);
070: }
071: // assert table.getTableName() != null;
072: tables.put(tableName, table);
073: }
074: return table;
075: }
076:
077: public Collection tableCollection() {
078: return tables.entrySet();
079: }
080:
081: public boolean containsTable(String tableName) {
082: return tables.containsKey(tableName);
083: }
084:
085: public int size() {
086: return tables.size();
087: }
088:
089: public final Map toInternalMap() {
090: final Map modelMap = new LinkedHashMap();
091:
092: final Map tableMap = new LinkedHashMap();
093:
094: modelMap.put(TABLES_TAG, tableMap);
095:
096: for (Iterator it = tables.keySet().iterator(); it.hasNext();) {
097: String tableName = (String) it.next();
098: MetaTable table = (MetaTable) tables.get(tableName);
099: tableMap.put(table.getTableName(), table.toInternalMap());
100: }
101:
102: return modelMap;
103: }
104:
105: public final Map toExternalMap() {
106: final Map modelMap = new LinkedHashMap();
107:
108: final Map tableMap = new LinkedHashMap();
109:
110: modelMap.put(TABLES_TAG, tableMap);
111:
112: for (Iterator it = tables.keySet().iterator(); it.hasNext();) {
113: String tableName = (String) it.next();
114: MetaTable table = (MetaTable) tables.get(tableName);
115: tableMap.put(table.getTableName(), table.toExternalMap());
116: }
117:
118: return modelMap;
119: }
120:
121: /**
122: * This method must be called before fromInternalMap since it populates
123: * aliases map.
124: *
125: * @param modelMap
126: */
127: public final void fromExternalMap(Map modelMap) {
128:
129: Map tablesMap = (Map) modelMap.get(TABLES_TAG);
130: // assert tablesMap != null;
131:
132: for (Iterator it = tablesMap.keySet().iterator(); it.hasNext();) {
133: String tableKey = (String) it.next();
134: Map tableMap = (Map) tablesMap.get(tableKey);
135: String tableName = (String) tableMap.get(TABLE_NAME_TAG);
136: String tableAlias = (String) tableMap.get(TABLE_ALIAS_TAG);
137: // assert tableName != null : "tableName is null";
138: // assert tableAlias != null: "tableAlias is null";
139:
140: if (filter.isAllowed(tableName)) {
141: MetaTable table = (MetaTable) tables.get(tableName);
142: if (table != null) {
143: table.fromExternalMap(tableMap);
144: // MetaTable.ForeignKeys fks = table.getForeignKeys();
145: tables.put(tableName, table);
146: }
147: }
148: }
149: }
150:
151: public final void fromInternalMap(Map modelMap) {
152: Map tablesMap = (Map) modelMap.get(TABLES_TAG);
153: // assert tablesMap != null;
154:
155: for (Iterator it = tablesMap.keySet().iterator(); it.hasNext();) {
156: String tableKey = (String) it.next();
157: Map tableMap = (Map) tablesMap.get(tableKey);
158: String tableName = (String) tableMap.get(TABLE_NAME_TAG);
159: // assert tableName != null : "tableName is null";
160:
161: if (filter.isAllowed(tableName)) {
162: MetaTable table = (MetaTable) tables.get(tableName);
163: if (table == null) {
164: table = new MetaTable(tableName);
165: }
166: table.fromInternalMap(tableMap);
167: tables.put(tableName, table);
168: } else {
169: System.err.println("TABLE " + tableName
170: + " does not match pattern "
171: + filter.toString());
172: }
173:
174: }
175: }
176:
177: public UserDefinedTypeMetaModel getUserDefinedTypeMetaModel() {
178: return userDefinedTypeMetaModel;
179: }
180:
181: public void setUserDefinedTypeMetaModel(
182: UserDefinedTypeMetaModel userDefinedTypeMetaModel) {
183: this .userDefinedTypeMetaModel = userDefinedTypeMetaModel;
184: }
185:
186: public String toString() {
187: return "MetaModel = {" + "tables = " + tables + "\n}";
188: }
189:
190: public MetaTableIterator tableIterator() {
191: return new MetaTableIterator(this );
192: }
193:
194: //
195: //
196: // Util classes:
197: //
198: //
199: public final static class DefaultModelFilter implements ModelFilter {
200:
201: public static final String NOT = "!";
202:
203: private List filterTokens = new ArrayList();
204:
205: public DefaultModelFilter(String filter) {
206: if (filter != null) {
207: tokenize(filter);
208: }
209: }
210:
211: public boolean isAllowed(String name) {
212: if (getFilterTokens().size() == 0) {
213: return true;
214: } else if (name == null || name.length() == 0) {
215: return false;
216: }
217: boolean rc = false;
218: for (int i = 0; i < getFilterTokens().size(); i++) {
219: String generalizedToken = (String) getFilterTokens()
220: .get(i);
221: String token = generalizedToken;
222: boolean negate = false;
223: if (generalizedToken.startsWith(NOT)) {
224: token = generalizedToken.substring(NOT.length(),
225: generalizedToken.length());
226: negate = true;
227: }
228:
229: if (negate) {
230: if (!name.startsWith(token)) {
231: rc = true;
232: break;
233: }
234: } else {
235: if (name.startsWith(token)) {
236: rc = true;
237: break;
238: }
239: }
240: }
241: return rc;
242: }
243:
244: protected void tokenize(String filter) {
245: StringTokenizer tokenizer = new StringTokenizer(filter,
246: DELIMITER);
247:
248: while (tokenizer.hasMoreTokens()) {
249: String token = tokenizer.nextToken();
250: filterTokens.add(token);
251: }
252: }
253:
254: protected List getFilterTokens() {
255: return filterTokens;
256: }
257: }
258:
259: public final static class RegExpModelFilter implements ModelFilter {
260:
261: private Pattern filterPattern;
262: private String stringPattern;
263:
264: public RegExpModelFilter(String filter) {
265: if (filter != null) {
266: prepare(filter);
267: }
268: }
269:
270: public boolean isAllowed(String name) {
271: Matcher m = filterPattern.matcher(name);
272: return m.matches();
273: }
274:
275: protected void prepare(String filter) {
276: if (filter == null || filter.trim().length() == 0) {
277: throw new IllegalArgumentException(
278: "Filter pattern is empty");
279: }
280: if (!isRegExp(filter)) {
281: throw new IllegalArgumentException(
282: "Filter pattern does no start/end with "
283: + REG_EXP_ENCLOSE_CHAR
284: + "; filter pattern = " + filter);
285: }
286:
287: stringPattern = filter.substring(1, filter.length() - 1);
288: filterPattern = Pattern.compile(stringPattern);
289: }
290:
291: public static boolean isRegExp(String pattern) {
292: return pattern.startsWith(REG_EXP_ENCLOSE_CHAR)
293: && pattern.endsWith(REG_EXP_ENCLOSE_CHAR);
294: }
295:
296: public String toString() {
297: return stringPattern != null ? stringPattern : super
298: .toString();
299: }
300:
301: }
302:
303: /**
304: *
305: */
306: public static class MetaTableIterator implements Iterator {
307: private Iterator iterator;
308:
309: public MetaTableIterator(MetaModel model) {
310: iterator = model.tables.entrySet().iterator();
311: }
312:
313: public boolean hasNext() {
314: return iterator.hasNext();
315: }
316:
317: public Object next() {
318: return iterator.next();
319: }
320:
321: public MetaTable nextMetaTable() {
322: Map.Entry entry = (Map.Entry) next();
323: return (MetaTable) entry.getValue();
324: }
325:
326: public void remove() {
327: }
328: }
329:
330: }
|