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