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.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   // private HashMap indexs;
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) { // wich means we create the collection
00095       objectType = descriptor.getObjectType();
00096     } else { // We open an existing collection
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     // TODO : v�rifier que l'object est bien Serializable ou Externalizable.
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     // If we got there, our first index is a Unique-Index
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       // If we got there, our first index is a Unique-Index
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     // everything went fine :)
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       // If we got there, our first index is a Unique-Index
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       // If we got there, our first index is a Unique-Index
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         // index.delObjectWithKey(index.getKey(obj), elementPos);
00430         // ((FODBIndex) indexsbyMember.get(memberName)).delObjectWithKey(id,
00431         // elementPos);
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 }

Generated on Tue May 22 23:01:09 2007 for OpenMobileIS by  doxygen 1.5.1-p1