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
00058 private FastObjectDB database;
00059
00060 private Class objectType;
00061
00062
00063 private Array indexs;
00064
00065 private Hashtable indexsbyMember;
00066
00067 private FODBCollectionFile collectionFile;
00068
00069 private FODBCollectionIndexFile collectionFileLink;
00070
00085 private FODBCollection(FastObjectDB db, FODBCollectionDescriptor descriptor, FODBCollectionFile cf) throws BadDataFormatException, FODBException {
00086 name = descriptor.getCollectionName();
00087 database = db;
00088 collectionFile = cf;
00089 collectionFileLink = new FODBCollectionIndexFile(cf);
00090 indexs = new Array(10);
00091 indexsbyMember = new Hashtable();
00092 if (descriptor.getObjectType() != null) {
00093 objectType = descriptor.getObjectType();
00094 } else {
00095 database.getTransactionManager().begin();
00096 database.getTransactionManager().enterTransaction(this.name);
00097 try {
00098 objectType = collectionFile.getObjectType();
00099 FODBIndexHeader[] indexsHeaders;
00100 indexsHeaders = collectionFile.getIndexsHeaders();
00101
00102 if (indexsHeaders != null) {
00103 FODBIndex index;
00104 for (int i = 0; i < indexsHeaders.length; i++) {
00105 index = FODBIndexFactory.getFactory().createIndex(indexsHeaders[i], objectType, collectionFileLink);
00106 if (index == null) {
00107 throw new FODBException("Internal Error : Can't open collection !!!");
00108 }
00109 indexs.add(indexsHeaders[i].getMemberName());
00110 indexsbyMember.put(indexsHeaders[i].getMemberName(), index);
00111 }
00112 }
00113 } catch (Throwable ex) {
00114 throw new FODBException(ex);
00115 } finally {
00116 database.getTransactionManager().commit();
00117 }
00118 }
00119 }
00120
00121 public FODBCollectionDescriptor getDescriptor() {
00122 return collectionFile.getDescriptor();
00123 }
00124
00125 public Class getCollectionObjectClass() {
00126 return objectType;
00127 }
00128
00129 public FODBIndex getIndexByMember(String member) {
00130 return (FODBIndex) indexsbyMember.get(member);
00131 }
00132
00133 public boolean isSynchronized() {
00134 return collectionFile.isSynchronized();
00135 }
00136
00149 public static FODBCollection createCollection(FastObjectDB db, FODBCollectionDescriptor descriptor) throws FODBException {
00150
00151 String completeFilePath = "" + db.getRootDir() + "/" + db.getName() + "/" + descriptor.getCollectionName() + ".col";
00152 try {
00153 FODBCollectionFile fcf = FODBCollectionFile.createCollection(completeFilePath, descriptor, db);
00154 return new FODBCollection(db, descriptor, fcf);
00155 } catch (Throwable ex) {
00156 throw new FODBException(ex);
00157 }
00158 }
00159
00170 public static FODBCollection openCollection(FastObjectDB db, String colName) throws FODBException {
00171 String completeFilePath = "" + db.getRootDir() + "/" + db.getName() + "/" + colName + ".col";
00172 try {
00173 FODBCollectionFile fcf = FODBCollectionFile.openCollection(completeFilePath, colName, db);
00174 return new FODBCollection(db, new FODBCollectionDescriptor(colName, null), fcf);
00175 } catch (Throwable ex) {
00176 throw new FODBException(ex);
00177 }
00178 }
00179
00180 public String getName() {
00181 return name;
00182 }
00183
00193 public void setCollectionCypher(FODBCypher cypher) throws FODBException {
00194 collectionFile.setCollectionCypher(cypher);
00195 }
00196
00202 public FODBCypher getCollectionCypher() throws FODBException {
00203 return collectionFile.getCollectionCypher();
00204 }
00205
00214 public boolean addIndex(FODBIndexDescriptor descriptor) throws FODBException {
00215 String memberName = descriptor.getMemberName();
00216 if (indexs.contains(memberName)) {
00217 return false;
00218 }
00219 database.getTransactionManager().begin();
00220 try {
00221 FODBIndex newIndex = FODBIndexFactory.getFactory().createIndex(descriptor, objectType, collectionFileLink);
00222
00223 if (newIndex == null) {
00224 System.out.println("" + descriptor.getName() + " ===> NULL !!!");
00225 return false;
00226 }
00227
00228 indexs.add(memberName);
00229 indexsbyMember.put(memberName, newIndex);
00230 return true;
00231 } catch (Throwable ex) {
00232 throw new FODBException(ex);
00233 } finally {
00234 database.getTransactionManager().commit();
00235 }
00236 }
00237
00238 public FODBIndex[] getCollectionIndexList() {
00239 FODBIndex[] ret = new FODBIndex[indexs.size()];
00240 for (int i = 0; i < indexs.size(); i++) {
00241 String memberName = (String) indexs.get(i);
00242 ret[i] = (FODBIndex) indexsbyMember.get(memberName);
00243 }
00244 return ret;
00245 }
00246
00247 public FODBUniqueIndex getCollectionIdIndex() throws FODBException {
00248 if (indexs.size() == 0) {
00249 throw new FODBException("Internal collection error (index arrayList empty).");
00250 }
00251 String firstIndexMember = (String) indexs.get(0);
00252 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(firstIndexMember);
00253 if (firstIndex.getType() != FODBIndex.UNIQUE) {
00254 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00255 }
00256
00257
00258 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00259 return uIndex;
00260 }
00261
00270 public boolean addElement(Object obj) throws FODBException {
00271 if (!objectType.isInstance(obj)) {
00272 throw new FODBException("Trying to add element of a wrong type.");
00273 }
00274
00275 if (indexs.size() == 0) {
00276 throw new FODBException("Trying to add element to a collection which doesn't have any index.");
00277 }
00278
00279 database.getTransactionManager().begin();
00280 try {
00281 long pos = collectionFile.writeObject(obj);
00282
00283 for (int i = 0; i < indexs.size(); i++) {
00284 try {
00285 String memberName = (String) indexs.get(i);
00286 ((FODBIndex) indexsbyMember.get(memberName)).add(obj, pos);
00287 } catch (Exception ex) {
00288 throw new FODBException(ex);
00289 }
00290 }
00291 } catch (Throwable ex) {
00292 throw new FODBException(ex);
00293 } finally {
00294 database.getTransactionManager().commit();
00295 }
00296
00297 return true;
00298 }
00299
00308 public boolean replaceElement(Object obj) throws FODBException {
00309 if (!objectType.isInstance(obj)) {
00310 throw new FODBException("Trying to add element of a wrong type.");
00311 }
00312
00313 if (indexs.isEmpty()) {
00314 throw new FODBException("Trying to replace element in an empty collection (doesn't have any index).");
00315 }
00316
00317 String memberName = (String) indexs.get(0);
00318 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00319
00320 if (firstIndex.getType() != FODBIndex.UNIQUE) {
00321 throw new FODBException("Trying to replace an element in a collection which doesn't have any Unique Index !");
00322 }
00323
00324 database.getTransactionManager().begin();
00325 try {
00326
00327 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00328 Object key = ((FODBIndex) uIndex).getKey(obj);
00329 long elementPos = uIndex.getKeyPosition(key);
00330
00331 if (elementPos == Node.NO_NODE) {
00332 return false;
00333 }
00334 this.deleteElementAtPos(elementPos);
00335 this.addElement(obj);
00336 } catch (Throwable ex) {
00337 throw new FODBException("Internal error !", ex);
00338 } finally {
00339 database.getTransactionManager().commit();
00340 }
00341
00342
00343 return true;
00344 }
00345
00354 public boolean deleteSingleElement(Object obj) throws FODBException {
00355 if (!objectType.isInstance(obj)) {
00356 throw new FODBException("Trying to delete element of a wrong type.");
00357 }
00358
00359 if (indexs.isEmpty()) {
00360 throw new FODBException("Trying to delete element from an empty collection (doesn't have any index).");
00361 }
00362
00363 String memberName = (String) indexs.get(0);
00364 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00365 if ((firstIndex).getType() != FODBIndex.UNIQUE) {
00366 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00367 }
00368
00369 database.getTransactionManager().begin();
00370 try {
00371
00372 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00373 Object key = ((FODBIndex) uIndex).getKey(obj);
00374 this.deleteObjectWithId(key);
00375 } catch (Exception ex) {
00376 throw new FODBException("Internal error !! Database might be corrupted !!!", ex);
00377 } finally {
00378 database.getTransactionManager().commit();
00379 }
00380
00381 return true;
00382 }
00383
00393 public boolean deleteObjectWithId(Object id) throws FODBException {
00394
00395 if (indexs.isEmpty()) {
00396 throw new FODBException("Trying to delete element from an empty collection (doesn't have any index).");
00397 }
00398
00399 String memberName = (String) indexs.get(0);
00400 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00401 if ((firstIndex).getType() != FODBIndex.UNIQUE) {
00402 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00403 }
00404
00405 database.getTransactionManager().begin();
00406 try {
00407
00408 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00409 long elementPos = uIndex.getKeyPosition(id);
00410
00411 if (elementPos == Node.NO_NODE) {
00412 return false;
00413 }
00414
00415 Object obj = getElementAtPos(elementPos);
00416
00417 for (int i = 0; i < indexs.size(); i++) {
00418 memberName = (String) indexs.get(i);
00419 FODBIndex index = (FODBIndex) indexsbyMember.get(memberName);
00420 index.delObjectWithKey(obj, elementPos);
00421
00422
00423
00424 }
00425 collectionFile.deleteObject(elementPos);
00426 } catch (Exception ex) {
00427 throw new FODBException("Internal error !! Database might be corrupted !!!", ex);
00428 } finally {
00429 database.getTransactionManager().commit();
00430 }
00431
00432 return true;
00433 }
00434
00435 public ForwardUniqueIndexIterator getForwardIndexIterator(String memberName) throws FODBException {
00436 FODBIndex index = (FODBIndex) indexsbyMember.get(memberName);
00437 if (index == null)
00438 throw new FODBException("index member not found in this collection");
00439 try {
00440 return new ForwardUniqueIndexIterator(index, this);
00441 } catch (IOException ex) {
00442 throw new FODBException(ex);
00443 } catch (ClassNotFoundException ex) {
00444 throw new FODBException(ex);
00445 }
00446 }
00447
00448 public BackwardUniqueIndexIterator getBackwardIndexIterator(String memberName) throws FODBException {
00449 FODBIndex index = (FODBIndex) indexsbyMember.get(memberName);
00450 if (index == null)
00451 throw new FODBException("index member not found in this collection");
00452 try {
00453 return new BackwardUniqueIndexIterator(index, this);
00454 } catch (IOException ex) {
00455 throw new FODBException(ex);
00456 } catch (ClassNotFoundException ex) {
00457 throw new FODBException(ex);
00458 }
00459 }
00460
00468 private void deleteElementAtPos(long objPos) throws FODBException {
00469 long posTab[] = new long[1];
00470 posTab[0] = objPos;
00471 deleteElements(posTab);
00472 }
00473
00481 private void deleteElements(long[] objPos) throws FODBException {
00482 if (indexs.isEmpty()) {
00483 throw new FODBException("Trying to remove an element from an empty collection.");
00484 }
00485
00486 Object objToDelete = null;
00487 for (int j = 0; j < objPos.length; j++) {
00488 objToDelete = getElementAtPos(objPos[j]);
00489 this.deleteSingleElement(objToDelete);
00490 }
00491 }
00492
00501 public Object getElementAtPos(long pos) throws FODBException {
00502 Object result;
00503 try {
00504 database.getTransactionManager().validateThread(Thread.currentThread());
00505 result = collectionFile.readObject(pos);
00506 return result;
00507 } catch (Exception ex) {
00508 throw new FODBException(ex);
00509 }
00510 }
00511
00520 protected Object getNodeAtPos(long pos) throws FODBException {
00521 Object result;
00522 try {
00523 result = collectionFile.readNode(pos);
00524 return result;
00525 } catch (Throwable ex) {
00526 throw new FODBException(ex);
00527 }
00528 }
00529
00533 public FastObjectDB getDatabase() {
00534 return database;
00535 }
00536
00537 }