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

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   private FastObjectDB database;
00058 
00059   private Class objectType;
00060 
00061   //    private HashMap indexs;
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) { // wich means we create the collection
00087       objectType = objType;
00088     } else { // We open an existing collection
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     // TODO : vérifier que l'object est bien Serializable ou Externalizable.
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     // If we got there, our first index is a Unique-Index
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       // If we got there, our first index is a Unique-Index
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     // everything went fine :)
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       // If we got there, our first index is a Unique-Index
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                         // If we got there, our first index is a Unique-Index
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                                 //index.delObjectWithKey(index.getKey(obj), elementPos);
00414 //                              ((FODBIndex) indexsbyMember.get(memberName)).delObjectWithKey(id, elementPos);
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 }

Generated on Thu Oct 6 10:06:32 2005 for OpenMobileIS by  doxygen 1.4.3