001: /**
002: * Copyright (C) 2007 NetMind Consulting Bt.
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 3 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package hu.netmind.persistence;
018:
019: import java.util.*;
020: import hu.netmind.persistence.parser.*;
021:
022: /**
023: * Map implementation with LazyList backing.
024: * @author Brautigam Robert
025: * @version Revision: $Revision$
026: */
027: public class MapHandler extends ContainerHandler {
028: /**
029: * Constructor.
030: */
031: public MapHandler(StoreContext context) {
032: super (context);
033: }
034:
035: public Class getContainerClass() {
036: return MapImpl.class;
037: }
038:
039: /**
040: * Create the subtable.
041: */
042: public void ensureTableExists(ClassInfo parentInfo,
043: String attributeName, boolean create) {
044: Transaction tx = context.getTransactionTracker()
045: .getTransaction(TransactionTracker.TX_REQUIRED);
046: tx.begin();
047: try {
048: // Ensure map helper table
049: HashMap mapAttributeTypes = new HashMap();
050: mapAttributeTypes.put("persistence_id", Long.class);
051: mapAttributeTypes.put("persistence_start", Long.class);
052: mapAttributeTypes.put("persistence_end", Long.class);
053: mapAttributeTypes.put("persistence_txstartid", Long.class);
054: mapAttributeTypes.put("persistence_txstart", Long.class);
055: mapAttributeTypes.put("persistence_txendid", Long.class);
056: mapAttributeTypes.put("persistence_txend", Long.class);
057: mapAttributeTypes.put("container_key", String.class);
058: mapAttributeTypes.put("value", Long.class);
059: Vector mapKeys = new Vector();
060: mapKeys.add("persistence_id");
061: mapKeys.add("persistence_txstart");
062: mapKeys.add("container_key");
063: context.getDatabase().ensureTable(tx,
064: parentInfo.getSubTableName(attributeName),
065: mapAttributeTypes, mapKeys, create);
066: } catch (StoreException e) {
067: tx.markRollbackOnly();
068: throw e;
069: } catch (Throwable e) {
070: tx.markRollbackOnly();
071: throw new StoreException("Unknown exception", e);
072: } finally {
073: tx.commit();
074: }
075: }
076:
077: /**
078: * Create the approriate symbol entry when parsing a query.
079: */
080: public WhereResolver.SymbolTableEntry getSymbolEntry(
081: AttributeSpecifier spec,
082: WhereResolver.SymbolTableEntry previousEntry,
083: ClassInfo previousInfo, ReferenceTerm previousTerm) {
084: String attributeName = spec.getIdentifier();
085: // Create entry
086: WhereResolver.SymbolTableEntry entry = new WhereResolver.SymbolTableEntry();
087: entry.alias = null;
088: if (spec.getKeyname() != null) {
089: // If a specific map object was specified, then this is to
090: // be remembered.
091: entry.alias = spec.getIdentifier() + "["
092: + spec.getKeyname() + "]";
093: }
094: entry.tableName = previousInfo.getSubTableName(attributeName);
095: entry.automatic = true;
096: entry.type = WhereResolver.SymbolTableEntry.TYPE_HANDLED;
097: entry.referenceColumn = "value";
098: // Create expression.
099: Expression connectorExpression = new Expression();
100: ReferenceTerm leftTerm1 = previousTerm;
101: if (previousEntry.automatic)
102: previousEntry.termList.add(leftTerm1);
103: ReferenceTerm rightTerm1 = new ReferenceTerm(entry.tableName,
104: entry.alias, "persistence_id");
105: entry.termList.add(rightTerm1);
106: connectorExpression.add(leftTerm1);
107: connectorExpression.add("=");
108: connectorExpression.add(rightTerm1);
109: // This subexpression is only important, if
110: // there are more attributes to follow
111: if ((spec.getKeyname() != null)
112: && (!"".equals(spec.getKeyname()))) {
113: connectorExpression.add("and");
114: ReferenceTerm leftTerm2 = new ReferenceTerm(
115: entry.tableName, entry.alias, "container_key");
116: entry.termList.add(leftTerm2);
117: ConstantTerm rightTerm2 = new ConstantTerm(spec
118: .getKeyname());
119: connectorExpression.add(leftTerm2);
120: connectorExpression.add("=");
121: connectorExpression.add(rightTerm2);
122: }
123: // Expression
124: entry.expression = connectorExpression;
125: // Return entry
126: return entry;
127: }
128:
129: /**
130: * Determine the next class info after the given specifier.
131: */
132: public ClassInfo getSymbolInfo(
133: WhereResolver.SymbolTableEntry entry,
134: AttributeSpecifier spec) throws ParserException {
135: if (spec.getClassName() == null)
136: throw new ParserException(ParserException.SYMBOL_ERROR,
137: "class was not given after map reference");
138: ClassInfo previousInfo = context.getClassTracker()
139: .getMatchingClassInfo(spec.getClassName());
140: if (previousInfo == null)
141: throw new ParserException(ParserException.SYMBOL_ERROR,
142: "could not find class to map item classname: "
143: + spec.getClassName());
144: return previousInfo;
145: }
146: }
|