Main Page | Packages | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

FODBCollection.java

00001 /*
00002  * OpenMobileIS - a free Java(TM) Framework for mobile applications Java(TM)
00003  * Copyright (C) 2004-2005 Philippe Delrieu
00004  * All rights reserved.
00005  * Contact: openmobileis@e-care.fr
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00020  * USA
00021  *
00022  *  Author : Philippe Delrieu
00023  *  
00024  *  Modifications :
00025  *  2004 Creation P.Delrieu
00026  *  2004 Modified by Romain Beaugrand
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   // private HashMap indexs;
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) { // wich means we create the collection
00093       objectType = descriptor.getObjectType();
00094     } else { // We open an existing collection
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     // TODO : v�rifier que l'object est bien Serializable ou Externalizable.
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     // If we got there, our first index is a Unique-Index
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       // If we got there, our first index is a Unique-Index
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     // everything went fine :)
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       // If we got there, our first index is a Unique-Index
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       // If we got there, our first index is a Unique-Index
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         // index.delObjectWithKey(index.getKey(obj), elementPos);
00422         // ((FODBIndex) indexsbyMember.get(memberName)).delObjectWithKey(id,
00423         // elementPos);
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 }

Generated on Wed Dec 14 21:05:33 2005 for OpenMobileIS by  doxygen 1.4.4