001: /*
002: This source file is part of Smyle, a database library.
003: For up-to-date information, see http://www.drjava.de/smyle
004: Copyright (C) 2001 Stefan Reich (doc@drjava.de)
005:
006: This library is free software; you can redistribute it and/or
007: modify it under the terms of the GNU Lesser General Public
008: License as published by the Free Software Foundation; either
009: version 2.1 of the License, or (at your option) any later version.
010:
011: This library is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019:
020: For full license text, see doc/license/lgpl.txt in this distribution
021: */
022:
023: package drjava.smyle.core;
024:
025: import java.util.*;
026: import org.artsProject.mcop.*;
027: import drjava.smyle.meta.*;
028:
029: public class Index<T extends Struct<T>> implements Marshallable {
030: TableImpl<T> table;
031: ArrayList<Function> fields;
032: PersistentBTree<UniversalKey, ChunkRefs> tree;
033:
034: public Index(TableImpl<T> table, ArrayList<Function> fields) {
035: this .table = table;
036: this .fields = fields;
037: buildTree();
038: }
039:
040: public Index(TableImpl<T> table, Buffer b) {
041: this .table = table;
042: fields = new ArrayList<Function>();
043: MCOP.readSeq(b, fields, table.fmd);
044: tree = new PersistentBTree<UniversalKey, ChunkRefs>(
045: TableImpl.INDEX_M, null, new UniversalKey.MarDemar(),
046: new TypeMarDemar(ChunkRefs.DEMARSHALLER),
047: table.snapshot.newChunkManager, new ChunkRef(b));
048: // TODO: load on demand?
049: }
050:
051: public BTree<UniversalKey, ChunkRefs> getTree() {
052: return tree;
053: }
054:
055: private void buildTree() {
056: synchronized (table.snapshot) {
057: tree = new PersistentBTree<UniversalKey, ChunkRefs>(
058: TableImpl.INDEX_M, null,
059: new UniversalKey.MarDemar(), new TypeMarDemar(
060: ChunkRefs.DEMARSHALLER),
061: table.snapshot.newChunkManager, null);
062: for (int i = 0; i < table.elements.size(); i++) {
063: T t = table.loadElement(i);
064: UniversalKey key = keyForElement(t);
065: ChunkRefs cr = tree.get(key);
066: if (cr == null)
067: cr = new ChunkRefs();
068: cr.listAdd(new ChunkRef(table.elements.get(i)));
069: tree.put(key, cr);
070: }
071: }
072: }
073:
074: private UniversalKey keyForElement(T t) {
075: UniversalKey[] keys = new UniversalKey[fields.size()];
076: for (int j = 0; j < fields.size(); j++)
077: keys[j] = table
078: .cutKey(new UniversalKey(fields.get(j).of(t)));
079: return UniversalKey.concatDimensions(keys);
080: }
081:
082: public void addField(Function f) {
083: fields.add(f);
084: buildTree();
085: }
086:
087: public UniversalKey makeKeyPrefix(Filter<T> filter) {
088: ArrayList<Object> list = new ArrayList<Object>();
089: for (int i = 0; i < fields.size(); i++) {
090: Filter<T>.Clause c = findClause(filter, fields.get(i));
091: if (c == null)
092: break;
093: list.add(table.cutKey(new UniversalKey(c.getValue())));
094: }
095: return UniversalKey.concatDimensions(list
096: .toArray(new Object[list.size()]));
097: }
098:
099: private Filter<T>.Clause findClause(Filter<T> filter, Function f) {
100: // TODO: optimize
101: for (int i = 0; i < filter._numClauses(); i++) {
102: Filter<T>.Clause c = filter._getClause(i);
103: if (f.equals(c.getFunction()))
104: return c;
105: }
106: return null;
107: }
108:
109: public void clear() {
110: tree.clear();
111: }
112:
113: public void marshal(Buffer b) {
114: MCOP.writeSeq(b, fields);
115: tree.flush().marshal(b);
116: }
117:
118: public void add(T t, ChunkRef chunk) {
119: UniversalKey key = keyForElement(t);
120: ChunkRefs cr = tree.get(key);
121: //if (debug) System.out.println("Adding to index: "+indexedFields.get(0).of(t)+", crs: "+cr);
122: if (cr == null)
123: cr = new ChunkRefs();
124: cr.listAdd(chunk);
125: tree.put(key, cr);
126: }
127:
128: public void remove(T t, ChunkRef chunk) {
129: UniversalKey key = keyForElement(t);
130: ChunkRefs cr = tree.get(key);
131: if (cr.list.size() == 1) {
132: tree.remove(key);
133: } else {
134: cr.list.remove(chunk);
135: tree.put(key, cr);
136: }
137: }
138:
139: public void collectChunks(BitSet whiteList) {
140: tree.collectChunks(whiteList);
141: }
142: }
|