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.FODBUniqueIntIndex;
00042 import org.openmobileis.database.fastobjectdb.db.index.FODBUniqueLongIndex;
00043 import org.openmobileis.database.fastobjectdb.db.index.node.Node;
00044 import org.openmobileis.database.fastobjectdb.db.store.FODBCollectionFile;
00045 import org.openmobileis.database.fastobjectdb.db.store.FODBCollectionIndexFile;
00046
00047 import org.openmobileis.common.util.collection.Array;
00048 import org.openmobileis.common.util.exception.BadDataFormatException;
00049
00057 public class FODBCollection {
00058 private String name;
00059
00060 private FastObjectDB database;
00061
00062 private Class objectType;
00063
00064
00065 private Array indexs;
00066
00067 private Hashtable indexsbyMember;
00068
00069 private FODBCollectionFile collectionFile;
00070
00071 private FODBCollectionIndexFile collectionFileLink;
00072
00087 private FODBCollection(FastObjectDB db, FODBCollectionDescriptor descriptor, FODBCollectionFile cf) throws BadDataFormatException, FODBException {
00088 name = descriptor.getCollectionName();
00089 database = db;
00090 collectionFile = cf;
00091 collectionFileLink = new FODBCollectionIndexFile(cf);
00092 indexs = new Array(10);
00093 indexsbyMember = new Hashtable();
00094 if (descriptor.getObjectType() != null) {
00095 objectType = descriptor.getObjectType();
00096 } else {
00097 database.getTransactionManager().begin();
00098 database.getTransactionManager().enterTransaction(this.name);
00099 try {
00100 objectType = collectionFile.getObjectType();
00101 FODBIndexHeader[] indexsHeaders;
00102 indexsHeaders = collectionFile.getIndexsHeaders();
00103
00104 if (indexsHeaders != null) {
00105 FODBIndex index;
00106 for (int i = 0; i < indexsHeaders.length; i++) {
00107 index = FODBIndexFactory.getFactory().createIndex(indexsHeaders[i], objectType, collectionFileLink);
00108 if (index == null) {
00109 throw new FODBException("Internal Error : Can't open collection !!!");
00110 }
00111 indexs.add(indexsHeaders[i].getMemberName());
00112 indexsbyMember.put(indexsHeaders[i].getMemberName(), index);
00113 }
00114 }
00115 } catch (Throwable ex) {
00116 throw new FODBException(ex);
00117 } finally {
00118 database.getTransactionManager().commit();
00119 }
00120 }
00121 }
00122
00123 public FODBCollectionDescriptor getDescriptor() {
00124 return collectionFile.getDescriptor();
00125 }
00126
00127 public Class getCollectionObjectClass() {
00128 return objectType;
00129 }
00130
00131 public FODBIndex getIndexByMember(String member) {
00132 return (FODBIndex) indexsbyMember.get(member);
00133 }
00134
00135 public boolean isSynchronized() {
00136 return collectionFile.isSynchronized();
00137 }
00138
00151 public static FODBCollection createCollection(FastObjectDB db, FODBCollectionDescriptor descriptor) throws FODBException {
00152
00153 String completeFilePath = "" + db.getRootDir() + "/" + db.getName() + "/" + descriptor.getCollectionName() + ".col";
00154 try {
00155 FODBCollectionFile fcf = FODBCollectionFile.createCollection(completeFilePath, descriptor, db);
00156 return new FODBCollection(db, descriptor, fcf);
00157 } catch (Throwable ex) {
00158 throw new FODBException(ex);
00159 }
00160 }
00161
00172 public static FODBCollection openCollection(FastObjectDB db, String colName) throws FODBException {
00173 String completeFilePath = "" + db.getRootDir() + "/" + db.getName() + "/" + colName + ".col";
00174 try {
00175 FODBCollectionFile fcf = FODBCollectionFile.openCollection(completeFilePath, colName, db);
00176 return new FODBCollection(db, new FODBCollectionDescriptor(colName, null), fcf);
00177 } catch (Throwable ex) {
00178 throw new FODBException(ex);
00179 }
00180 }
00181
00182 public String getName() {
00183 return name;
00184 }
00185
00195 public void setCollectionCypher(FODBCypher cypher) throws FODBException {
00196 collectionFile.setCollectionCypher(cypher);
00197 }
00198
00204 public FODBCypher getCollectionCypher() throws FODBException {
00205 return collectionFile.getCollectionCypher();
00206 }
00207
00216 public boolean addIndex(FODBIndexDescriptor descriptor) throws FODBException {
00217 String memberName = descriptor.getMemberName();
00218 if (indexs.contains(memberName)) {
00219 return false;
00220 }
00221 database.getTransactionManager().begin();
00222 try {
00223 FODBIndex newIndex = FODBIndexFactory.getFactory().createIndex(descriptor, objectType, collectionFileLink);
00224
00225 if (newIndex == null) {
00226 System.out.println("" + descriptor.getName() + " ===> NULL !!!");
00227 return false;
00228 }
00229
00230 indexs.add(memberName);
00231 indexsbyMember.put(memberName, newIndex);
00232 return true;
00233 } catch (Throwable ex) {
00234 throw new FODBException(ex);
00235 } finally {
00236 database.getTransactionManager().commit();
00237 }
00238 }
00239
00240 public FODBIndex[] getCollectionIndexList() {
00241 FODBIndex[] ret = new FODBIndex[indexs.size()];
00242 for (int i = 0; i < indexs.size(); i++) {
00243 String memberName = (String) indexs.get(i);
00244 ret[i] = (FODBIndex) indexsbyMember.get(memberName);
00245 }
00246 return ret;
00247 }
00248
00249 public FODBUniqueIndex getCollectionIdIndex() throws FODBException {
00250 if (indexs.size() == 0) {
00251 throw new FODBException("Internal collection error (index arrayList empty).");
00252 }
00253 String firstIndexMember = (String) indexs.get(0);
00254 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(firstIndexMember);
00255 if (firstIndex.getType() != FODBIndex.UNIQUE) {
00256 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00257 }
00258
00259
00260 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00261 return uIndex;
00262 }
00263
00272 public boolean addElement(Object obj) throws FODBException {
00273 if (!objectType.isInstance(obj)) {
00274 throw new FODBException("Trying to add element of a wrong type.");
00275 }
00276
00277 if (indexs.size() == 0) {
00278 throw new FODBException("Trying to add element to a collection which doesn't have any index.");
00279 }
00280
00281 database.getTransactionManager().begin();
00282 try {
00283 long pos = collectionFile.writeObject(obj);
00284
00285 for (int i = 0; i < indexs.size(); i++) {
00286 try {
00287 String memberName = (String) indexs.get(i);
00288 ((FODBIndex) indexsbyMember.get(memberName)).add(obj, pos);
00289 } catch (Exception ex) {
00290 throw new FODBException(ex);
00291 }
00292 }
00293 } catch (Throwable ex) {
00294 throw new FODBException(ex);
00295 } finally {
00296 database.getTransactionManager().commit();
00297 }
00298
00299 return true;
00300 }
00301
00310 public boolean replaceElement(Object obj) throws FODBException {
00311 if (!objectType.isInstance(obj)) {
00312 throw new FODBException("Trying to add element of a wrong type.");
00313 }
00314
00315 if (indexs.isEmpty()) {
00316 throw new FODBException("Trying to replace element in an empty collection (doesn't have any index).");
00317 }
00318
00319 String memberName = (String) indexs.get(0);
00320 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00321
00322 if (firstIndex.getType() != FODBIndex.UNIQUE) {
00323 throw new FODBException("Trying to replace an element in a collection which doesn't have any Unique Index !");
00324 }
00325
00326 database.getTransactionManager().begin();
00327 try {
00328
00329 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00330 Object key = ((FODBIndex) uIndex).getKey(obj);
00331 long elementPos = uIndex.getKeyPosition(key);
00332
00333 if (elementPos == Node.NO_NODE) {
00334 return false;
00335 }
00336 this.deleteElementAtPos(elementPos);
00337 this.addElement(obj);
00338 } catch (Throwable ex) {
00339 throw new FODBException("Internal error !", ex);
00340 } finally {
00341 database.getTransactionManager().commit();
00342 }
00343
00344
00345 return true;
00346 }
00347
00356 public boolean deleteSingleElement(Object obj) throws FODBException {
00357 if (!objectType.isInstance(obj)) {
00358 throw new FODBException("Trying to delete element of a wrong type.");
00359 }
00360
00361 if (indexs.isEmpty()) {
00362 throw new FODBException("Trying to delete element from an empty collection (doesn't have any index).");
00363 }
00364
00365 String memberName = (String) indexs.get(0);
00366 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00367 if ((firstIndex).getType() != FODBIndex.UNIQUE) {
00368 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00369 }
00370
00371 database.getTransactionManager().begin();
00372 try {
00373
00374 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00375 Object key = ((FODBIndex) uIndex).getKey(obj);
00376 this.deleteObjectWithId(key);
00377 } catch (Exception ex) {
00378 throw new FODBException("Internal error !! Database might be corrupted !!!", ex);
00379 } finally {
00380 database.getTransactionManager().commit();
00381 }
00382
00383 return true;
00384 }
00385
00395 public boolean deleteObjectWithId(Object objid) throws FODBException {
00396
00397 if (indexs.isEmpty()) {
00398 throw new FODBException("Trying to delete element from an empty collection (doesn't have any index).");
00399 }
00400
00401 String memberName = (String) indexs.get(0);
00402 FODBIndex firstIndex = (FODBIndex) indexsbyMember.get(memberName);
00403 if ((firstIndex).getType() != FODBIndex.UNIQUE) {
00404 throw new FODBException("Trying to delete single element in a Collection which only contains multiple indexs. Use the query delete method to do so.");
00405 }
00406
00407 database.getTransactionManager().begin();
00408 try {
00409
00410 FODBUniqueIndex uIndex = (FODBUniqueIndex) firstIndex;
00411 Object id = objid;
00412 if (uIndex instanceof FODBUniqueIntIndex && objid instanceof String) {
00413 id = Integer.getInteger((String)objid);
00414 } else if (uIndex instanceof FODBUniqueLongIndex && objid instanceof String) {
00415 id = Long.getLong((String)objid);
00416 }
00417 long elementPos = uIndex.getKeyPosition(id);
00418
00419 if (elementPos == Node.NO_NODE) {
00420 return false;
00421 }
00422
00423 Object obj = getElementAtPos(elementPos);
00424
00425 for (int i = 0; i < indexs.size(); i++) {
00426 memberName = (String) indexs.get(i);
00427 FODBIndex index = (FODBIndex) indexsbyMember.get(memberName);
00428 index.delObjectWithKey(obj, elementPos);
00429
00430
00431
00432 }
00433 collectionFile.deleteObject(elementPos);
00434 } catch (Exception ex) {
00435 throw new FODBException("Internal error !! Database might be corrupted !!!", ex);
00436 } finally {
00437 database.getTransactionManager().commit();
00438 }
00439
00440 return true;
00441 }
00442
00443 public ForwardUniqueIndexIterator getForwardIndexIterator(String memberName) throws FODBException {
00444 FODBIndex index = (FODBIndex) indexsbyMember.get(memberName);
00445 if (index == null)
00446 throw new FODBException("index member not found in this collection");
00447 try {
00448 return new ForwardUniqueIndexIterator(index, this);
00449 } catch (IOException ex) {
00450 throw new FODBException(ex);
00451 } catch (ClassNotFoundException ex) {
00452 throw new FODBException(ex);
00453 }
00454 }
00455
00456 public BackwardUniqueIndexIterator getBackwardIndexIterator(String memberName) throws FODBException {
00457 FODBIndex index = (FODBIndex) indexsbyMember.get(memberName);
00458 if (index == null)
00459 throw new FODBException("index member not found in this collection");
00460 try {
00461 return new BackwardUniqueIndexIterator(index, this);
00462 } catch (IOException ex) {
00463 throw new FODBException(ex);
00464 } catch (ClassNotFoundException ex) {
00465 throw new FODBException(ex);
00466 }
00467 }
00468
00476 private void deleteElementAtPos(long objPos) throws FODBException {
00477 long posTab[] = new long[1];
00478 posTab[0] = objPos;
00479 deleteElements(posTab);
00480 }
00481
00489 private void deleteElements(long[] objPos) throws FODBException {
00490 if (indexs.isEmpty()) {
00491 throw new FODBException("Trying to remove an element from an empty collection.");
00492 }
00493
00494 Object objToDelete = null;
00495 for (int j = 0; j < objPos.length; j++) {
00496 objToDelete = getElementAtPos(objPos[j]);
00497 this.deleteSingleElement(objToDelete);
00498 }
00499 }
00500
00509 public Object getElementAtPos(long pos) throws FODBException {
00510 Object result;
00511 try {
00512 database.getTransactionManager().validateThread(Thread.currentThread());
00513 result = collectionFile.readObject(pos);
00514 return result;
00515 } catch (Exception ex) {
00516 throw new FODBException(ex);
00517 }
00518 }
00519
00528 protected Object getNodeAtPos(long pos) throws FODBException {
00529 Object result;
00530 try {
00531 result = collectionFile.readNode(pos);
00532 return result;
00533 } catch (Throwable ex) {
00534 throw new FODBException(ex);
00535 }
00536 }
00537
00541 public FastObjectDB getDatabase() {
00542 return database;
00543 }
00544
00545 }