FODBCollection.java

00001 /*
00002  * OpenMobileIS - a free Java(TM) Framework for mobile applications Java(TM)
00003  * Copyright (C) 2004-2006 Philippe Delrieu
00004  * All rights reserved.
00005  * Contact: pdelrieu@openmobileis.org
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.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   // private HashMap indexs;
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) { // wich means we create the collection
00096       objectType = descriptor.getObjectType();
00097     } else { // We open an existing collection
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     // TODO : v�rifier que l'object est bien Serializable ou Externalizable.
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     // If we got there, our first index is a Unique-Index
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       // If we got there, our first index is a Unique-Index
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     // everything went fine :)
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       // If we got there, our first index is a Unique-Index
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       // If we got there, our first index is a Unique-Index
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         // index.delObjectWithKey(index.getKey(obj), elementPos);
00431         // ((FODBIndex) indexsbyMember.get(memberName)).delObjectWithKey(id,
00432         // elementPos);
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 }

Generated on Mon Dec 4 11:03:26 2006 for OpenMobileIS by  doxygen 1.5.1-p1