00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 package org.openmobileis.database.fastobjectdb.db;
00030
00031 import java.io.IOException;
00032 import java.util.Hashtable;
00033
00034 import org.openmobileis.database.fastobjectdb.*;
00035 import org.openmobileis.database.fastobjectdb.db.crypto.FODBCypher;
00036 import org.openmobileis.database.fastobjectdb.db.exception.FODBException;
00037 import org.openmobileis.database.fastobjectdb.db.index.FODBIndex;
00038 import org.openmobileis.database.fastobjectdb.db.index.FODBIndexFactory;
00039 import org.openmobileis.database.fastobjectdb.db.index.FODBIndexHeader;
00040 import org.openmobileis.database.fastobjectdb.db.index.FODBUniqueIndex;
00041 import org.openmobileis.database.fastobjectdb.db.index.node.Node;
00042 import org.openmobileis.database.fastobjectdb.db.store.FODBCollectionFile;
00043 import org.openmobileis.database.fastobjectdb.db.store.FODBCollectionIndexFile;
00044
00045 import org.openmobileis.common.util.collection.Array;
00046 import org.openmobileis.common.util.exception.BadDataFormatException;
00047
00055 public class FODBCollection {
00056 private String name;
00057 private FastObjectDB database;
00058
00059 private Class objectType;
00060
00061
00062 private Array indexs;
00063 private Hashtable indexsbyMember;
00064
00065 private FODBCollectionFile collectionFile;
00066 private FODBCollectionIndexFile collectionFileLink;
00067
00079 private FODBCollection(FastObjectDB db, String colName, FODBCollectionFile cf, Class objType) throws BadDataFormatException, FODBException {
00080 name = colName;
00081 database = db;
00082 collectionFile = cf;
00083 collectionFileLink = new FODBCollectionIndexFile(cf);
00084 indexs = new Array(10);
00085 indexsbyMember = new Hashtable();
00086 if (objType != null) {
00087 objectType = objType;
00088 } else {
00089 database.getTransactionManager().begin();
00090 database.getTransactionManager().enterTransaction(colName);
00091 try {
00092 objectType = collectionFile.getObjectType();
00093 FODBIndexHeader[] indexsHeaders;
00094 indexsHeaders = collectionFile.getIndexsHeaders();
00095
00096 if (indexsHeaders != null) {
00097 FODBIndex index;
00098 for (int i = 0; i < indexsHeaders.length; i++) {
00099 index = FODBIndexFactory.getFactory().createIndex(indexsHeaders[i], objectType, collectionFileLink);
00100 if (index == null) {
00101 throw new FODBException("Internal Error : Can't open collection !!!");
00102 }
00103 indexs.add(indexsHeaders[i].getMemberName());
00104 indexsbyMember.put(indexsHeaders[i].getMemberName(), index);
00105 }
00106 }
00107 } catch (Throwable ex) {
00108 throw new FODBException(ex);
00109 } finally {
00110 database.getTransactionManager().commit();
00111 }
00112 }
00113 }
00114
00115 public Class getCollectionObjectClass() {
00116 return objectType;
00117 }
00118
00119 public FODBIndex getIndexByMember(String member) {
00120 return (FODBIndex) indexsbyMember.get(member);
00121 }
00122
00123 public boolean isSynchronized() {
00124 return collectionFile.isSynchronized();
00125 }
00126
00127 public void setSynchronized(boolean sync) throws FODBException {
00128 database.getTransactionManager().begin();
00129 database.getTransactionManager().enterTransaction(this.getName());
00130 try {
00131 collectionFile.setSynchronized(sync);
00132 } catch (Throwable ex) {
00133 throw new FODBException(ex);
00134 } finally {
00135 database.getTransactionManager().commit();
00136 }
00137 }
00138
00148 public static FODBCollection createCollection(FastObjectDB db, String colName, Class objType) throws FODBException {
00149
00150 String completeFilePath = "" + db.getRootDir() + "/" + db.getName() + "/" + colName + ".col";
00151 try {
00152 FODBCollectionFile fcf = FODBCollectionFile.createCollection(completeFilePath, objType, colName, db);
00153 return new FODBCollection(db, colName, fcf, objType);
00154 } catch (Throwable ex) {
00155 throw new FODBException(ex);
00156 }
00157 }
00158
00167 public static FODBCollection openCollection(FastObjectDB db, String colName) throws FODBException {
00168 String completeFilePath = "" + db.getRootDir() + "/" + db.getName() + "/" + colName + ".col";
00169 try {
00170 FODBCollectionFile fcf = FODBCollectionFile.openCollection(completeFilePath, colName, db);
00171 return new FODBCollection(db, colName, fcf, null);
00172 } catch (Throwable ex) {
00173 throw new FODBException(ex);
00174 }
00175 }
00176
00177 public String getName() {
00178 return name;
00179 }
00180
00181
00190 public void setCollectionCypher(FODBCypher cypher) throws FODBException {
00191 collectionFile.setCollectionCypher(cypher);
00192 }
00193
00199 public FODBCypher getCollectionCypher() throws FODBException {
00200 return collectionFile.getCollectionCypher();
00201 }
00202
00210 public boolean addIndex(FODBIndexDescriptor descriptor) throws FODBException {
00211 String memberName = descriptor.getMemberName();
00212 if (indexs.contains(memberName)) {
00213 return false;
00214 }
00215 database.getTransactionManager().begin();
00216 try {
00217 FODBIndex newIndex = FODBIndexFactory.getFactory().createIndex(descriptor, objectType, collectionFileLink);
00218
00219 if (newIndex == null) {
00220 System.out.println("" + descriptor.getName() + " ===> NULL !!!");
00221 return false;
00222 }
00223
00224 indexs.add(memberName);
00225 indexsbyMember.put(memberName, newIndex);
00226 return true;
00227 } catch (Throwable ex) {
00228 throw new FODBException(ex);
00229 } finally {
00230 database.getTransactionManager().commit();
00231 }
00232 }
00233
00234 public FODBIndex[] getCollectionIndexList() {
00235 FODBIndex[] ret = new FODBIndex[indexs.size()];
00236 for ( int i=0; i<indexs.size(); i++) {
00237 String memberName = (String)indexs.get(i);
00238 ret[i] = (FODBIndex) indexsbyMember.get(memberName);
00239 }
00240 return ret;
00241 }
00242
00243 public FODBUniqueIndex getCollectionIdIndex() throws FODBException {
00244 if (indexs.size() == 0) {
00245 throw new FODBException("Internal collection error (index arrayList empty).");
00246 }
00247 String firstIndexMember = (String)indexs.get(0);
00248 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(firstIndexMember);
00249 if (firstIndex.getType() != FODBIndex.UNIQUE) {
00250 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00251 }
00252
00253
00254 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00255 return uIndex;
00256 }
00257
00265 public boolean addElement(Object obj) throws FODBException {
00266 if (!objectType.isInstance(obj)) {
00267 throw new FODBException("Trying to add element of a wrong type.");
00268 }
00269
00270 if (indexs.size() == 0) {
00271 throw new FODBException("Trying to add element to a collection which doesn't have any index.");
00272 }
00273
00274 database.getTransactionManager().begin();
00275 try {
00276 long pos = collectionFile.writeObject(obj);
00277
00278 for ( int i=0; i<indexs.size(); i++) {
00279 try {
00280 String memberName = (String)indexs.get(i);
00281 ((FODBIndex) indexsbyMember.get(memberName)).add(obj, pos);
00282 } catch (Exception ex) {
00283 throw new FODBException(ex);
00284 }
00285 }
00286 } catch (Throwable ex) {
00287 throw new FODBException(ex);
00288 } finally {
00289 database.getTransactionManager().commit();
00290 }
00291
00292 return true;
00293 }
00294
00302 public boolean replaceElement(Object obj) throws FODBException {
00303 if (!objectType.isInstance(obj)) {
00304 throw new FODBException("Trying to add element of a wrong type.");
00305 }
00306
00307 if (indexs.isEmpty()) {
00308 throw new FODBException("Trying to replace element in an empty collection (doesn't have any index).");
00309 }
00310
00311 String memberName = (String)indexs.get(0);
00312 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00313
00314 if (firstIndex.getType() != FODBIndex.UNIQUE) {
00315 throw new FODBException("Trying to replace an element in a collection which doesn't have any Unique Index !");
00316 }
00317
00318 database.getTransactionManager().begin();
00319 try {
00320
00321 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00322 Object key = ((FODBIndex)uIndex).getKey(obj);
00323 long elementPos = uIndex.getKeyPosition(key);
00324
00325 if (elementPos == Node.NO_NODE) {
00326 return false;
00327 }
00328 this.deleteElementAtPos(elementPos);
00329 this.addElement(obj);
00330 } catch (Throwable ex) {
00331 throw new FODBException("Internal error !", ex);
00332 } finally {
00333 database.getTransactionManager().commit();
00334 }
00335
00336
00337 return true;
00338 }
00339
00347 public boolean deleteSingleElement(Object obj) throws FODBException {
00348 if (!objectType.isInstance(obj)) {
00349 throw new FODBException("Trying to delete element of a wrong type.");
00350 }
00351
00352 if (indexs.isEmpty()) {
00353 throw new FODBException("Trying to delete element from an empty collection (doesn't have any index).");
00354 }
00355
00356 String memberName = (String)indexs.get(0);
00357 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00358 if ((firstIndex).getType() != FODBIndex.UNIQUE) {
00359 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00360 }
00361
00362 database.getTransactionManager().begin();
00363 try {
00364
00365 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00366 Object key = ((FODBIndex)uIndex).getKey(obj);
00367 this.deleteObjectWithId(key);
00368 } catch (Exception ex) {
00369 throw new FODBException("Internal error !! Database might be corrupted !!!", ex);
00370 } finally {
00371 database.getTransactionManager().commit();
00372 }
00373
00374 return true;
00375 }
00376
00385 public boolean deleteObjectWithId(Object id) throws FODBException {
00386
00387 if (indexs.isEmpty()) {
00388 throw new FODBException("Trying to delete element from an empty collection (doesn't have any index).");
00389 }
00390
00391 String memberName = (String)indexs.get(0);
00392 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00393 if ((firstIndex).getType() != FODBIndex.UNIQUE) {
00394 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00395 }
00396
00397 database.getTransactionManager().begin();
00398 try {
00399
00400 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00401 long elementPos = uIndex.getKeyPosition(id);
00402
00403 if (elementPos == Node.NO_NODE) {
00404 return false;
00405 }
00406
00407 Object obj = getElementAtPos(elementPos);
00408
00409 for ( int i=0; i<indexs.size(); i++) {
00410 memberName = (String)indexs.get(i);
00411 FODBIndex index = (FODBIndex)indexsbyMember.get(memberName);
00412 index.delObjectWithKey(obj, elementPos);
00413
00414
00415 }
00416 collectionFile.deleteObject(elementPos);
00417 } catch (Exception ex) {
00418 throw new FODBException("Internal error !! Database might be corrupted !!!", ex);
00419 } finally {
00420 database.getTransactionManager().commit();
00421 }
00422
00423 return true;
00424 }
00425
00426 public ForwardUniqueIndexIterator getForwardIndexIterator(String memberName) throws FODBException {
00427 FODBIndex index = (FODBIndex)indexsbyMember.get(memberName);
00428 if (index == null) throw new FODBException("index member not found in this collection");
00429 try {
00430 return new ForwardUniqueIndexIterator(index, this);
00431 } catch (IOException ex) {
00432 throw new FODBException(ex);
00433 } catch (ClassNotFoundException ex) {
00434 throw new FODBException(ex);
00435 }
00436 }
00437
00438 public BackwardUniqueIndexIterator getBackwardIndexIterator(String memberName) throws FODBException {
00439 FODBIndex index = (FODBIndex)indexsbyMember.get(memberName);
00440 if (index == null) throw new FODBException("index member not found in this collection");
00441 try {
00442 return new BackwardUniqueIndexIterator(index, this);
00443 } catch (IOException ex) {
00444 throw new FODBException(ex);
00445 } catch (ClassNotFoundException ex) {
00446 throw new FODBException(ex);
00447 }
00448 }
00449
00457 private void deleteElementAtPos(long objPos) throws FODBException {
00458 long posTab[] = new long[1];
00459 posTab[0] = objPos;
00460 deleteElements(posTab);
00461 }
00462
00469 private void deleteElements(long[] objPos) throws FODBException {
00470 if (indexs.isEmpty()) {
00471 throw new FODBException("Trying to remove an element from an empty collection.");
00472 }
00473
00474 Object objToDelete = null;
00475 for (int j = 0; j < objPos.length; j++) {
00476 objToDelete = getElementAtPos(objPos[j]);
00477 this.deleteSingleElement(objToDelete);
00478 }
00479 }
00480
00488 public Object getElementAtPos(long pos) throws FODBException {
00489 Object result;
00490 try {
00491 result = collectionFile.readObject(pos);
00492 return result;
00493 } catch (Throwable ex) {
00494 throw new FODBException(ex);
00495 }
00496 }
00497
00505 protected Object getNodeAtPos(long pos) throws FODBException {
00506 Object result;
00507 try {
00508 result = collectionFile.readNode(pos);
00509 return result;
00510 } catch (Throwable ex) {
00511 throw new FODBException(ex);
00512 }
00513 }
00514
00515
00519 public FastObjectDB getDatabase() {
00520 return database;
00521 }
00522
00523 }