FODBStringIndex.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.index;
00030 
00031 import java.io.IOException;
00032 import java.lang.reflect.*;
00033 
00034 import org.openmobileis.common.util.StringFormater;
00035 import org.openmobileis.common.util.collection.LongArray;
00036 import org.openmobileis.common.util.log.LogManager;
00037 import org.openmobileis.database.fastobjectdb.FODBIndexDescriptor;
00038 import org.openmobileis.database.fastobjectdb.FODBStringIndexDescriptor;
00039 import org.openmobileis.database.fastobjectdb.db.exception.FODBException;
00040 import org.openmobileis.database.fastobjectdb.db.exception.FODBQueryException;
00041 import org.openmobileis.database.fastobjectdb.db.index.node.StringNode;
00042 import org.openmobileis.database.fastobjectdb.db.index.node.Node;
00043 import org.openmobileis.database.fastobjectdb.db.query.soda.SodaIndexComparator;
00044 import org.openmobileis.database.fastobjectdb.db.query.soda.SodaStringIndexComparator;
00045 import org.openmobileis.database.fastobjectdb.db.store.FODBCollectionIndexFile;
00046 
00049 public abstract class FODBStringIndex extends FODBIndex {
00050   public FODBStringIndex(FODBIndexHeader newHeader, FODBCollectionIndexFile cFile, AccessibleObject accObj) throws FODBException {
00051     super(newHeader, cFile, accObj);
00052   }
00053 
00054   public FODBStringIndex(FODBStringIndexDescriptor descriptor, FODBCollectionIndexFile cFile, AccessibleObject accObj)
00055     throws FODBException {
00056     super(descriptor, cFile, accObj);
00057   }
00058 
00059   protected void specificDescriptorVerifications(FODBIndexDescriptor descriptor) throws FODBException {
00060     if (!(descriptor instanceof FODBStringIndexDescriptor)) {
00061       throw new FODBException("Internal Error");
00062     }
00063 
00064     FODBStringIndexDescriptor desc = (FODBStringIndexDescriptor) descriptor;
00065 
00066     // verify parameters
00067     if (desc.getOrder() < 3)
00068       throw new FODBException("ERROR Bad BTree order. BTree order must be more than 3");
00069     if (desc.getKeyLen() < 1)
00070                         throw new FODBException("ERROR Bad key length. key length must be more than 1");
00071  }
00072 
00073   protected Node initRoot(FODBIndexDescriptor descriptor) throws FODBException {
00074     FODBStringIndexDescriptor desc = (FODBStringIndexDescriptor) descriptor;
00075     return new StringNode(desc.getOrder(), desc.getKeyLen());
00076   }
00077 
00078   public Object getKey(Object obj) throws FODBException {
00079                 boolean isCaseSensitive = ((FODBStringIndexDescriptor)this.getIndexDescriptor()).isCaseSensitive();
00080                 return this.getKeySensitive(obj, isCaseSensitive);
00081         }
00082 
00083   public Object getKeySensitive(Object obj, boolean isCaseSensitive) throws FODBException {
00084     String key = null;
00085     if (accessObj instanceof Method) {
00086       try {
00087         key = (String) (((Method) accessObj).invoke(obj, new Object[0]));
00088         if (!isCaseSensitive)   {
00089                 key = StringFormater.removeAccent(key).toUpperCase();
00090         }
00091       } catch (InvocationTargetException ex) { 
00092         throw new FODBException("Unable to execute index's method", ex);
00093       } catch (IllegalAccessException ex) { 
00094         throw new FODBException("Unable to execute index's method", ex);
00095       }
00096     } else {
00097       try {
00098         key = (String) (((Field) accessObj).get(obj));
00099                                 if (!isCaseSensitive)   {
00100                                         key = StringFormater.removeAccent(key).toUpperCase();
00101                                 }
00102       } catch (IllegalAccessException ex) { 
00103         throw new FODBException("Unable to access index's field", ex);
00104       }
00105     }
00106 
00107     return key;
00108   }
00109 
00110   protected void insertKey(Object obj, long ptr) throws IOException, ClassNotFoundException, FODBException {
00111     String key = (String)obj;
00112 
00113     if (key == null) {
00114                         return; //no null key can be inserted.
00115 //      throw new FODBException("Trying to add an Element with invalid key: null key, collection : " + this.name );
00116     }
00117     if (key.length() == 0) {
00118         return; //no key with no element can be inserted.
00119      // throw new FODBException("Trying to add an Element with invalid key : key length 0, collection : " + this.name);
00120     }
00121     int keylength = ((FODBStringIndexDescriptor)header.descriptor).getKeyLen();
00122     if (key.length() > keylength) {
00123       key = key.substring(0, keylength);
00124     }
00125 
00126                 // search for the key
00127                 StringNode root = (StringNode) this.readRoot();
00128                 SearchResult searchResult = new SearchResult();
00129                 searchResult = this.search(root, key, searchResult);
00130 
00131                 if (searchResult.found) {
00132                         // As we called 'add', if we are in a UNIQUE index, we must
00133                         // return an exception.
00134                         if (getType() == UNIQUE) {
00135                                 throw new FODBException("Entry already present in Unique Index");
00136                         }
00137 
00138                         // store new data record pointer
00139                         //                long result = writeKeyPtr(ins.page, ins.pos, pos, oldPos);
00140                         // if we're in a MULTIPLE index, result is :
00141                         //      -> the new pos of the Pointer List if it grew up.
00142                         //      -> NULL_PTR if it didn't.
00143                         //                long modified = this.writeKeyPtr(ins.page, ins.pos, pos, oldPos);
00144                         this.writeKeyPtr(searchResult.node, searchResult.pos, ptr);
00145                         return;
00146                 }
00147                 if (getType() != UNIQUE) {
00148                         ptr = ((FODBMultipleStringIndex) this).createPtrArray(ptr);
00149                 }
00150                 StringNode btreenode = (StringNode) searchResult.node;
00151                 boolean flag;
00152                 for (flag = btreenode.pushInLeaf(key, searchResult.pos, ptr);
00153                         flag && btreenode.parentPtr != Node.NO_NODE;
00154                         btreenode = (StringNode) colFile.readNode(btreenode.parentPtr)) {
00155                         int i1 = this.minKey;
00156                         StringNode btreenode1 = new StringNode(header.descriptor.getOrder(), keylength);
00157                         btreenode1.parentPtr = btreenode.parentPtr;
00158                         int i;
00159                         for (i = i1 + 1; i < btreenode1.getMaxNbKey(); i++) {
00160                                 btreenode1.setKeyPtrAtPos(btreenode.getKeyAtPos(i), btreenode.getNodePtrAtPos(i), i - i1 - 1);
00161                                 btreenode1.branchs[i - i1 - 1] = btreenode.branchs[i];
00162                         }
00163 
00164                         btreenode1.branchs[i - i1 - 1] = btreenode.branchs[i];
00165                         btreenode1.nbKey = btreenode1.getMaxNbKey() - i1 - 1;
00166                         colFile.writeNode(btreenode1, header);
00167                         if (btreenode1.branchs[0] != Node.NO_NODE) {
00168                                 for (int j = 0; j <= btreenode1.nbKey; j++) {
00169                                         StringNode tempNode = (StringNode) colFile.readNode(btreenode1.branchs[j]);
00170                                         tempNode.parentPtr = btreenode1.filePtr;
00171                                         colFile.writeNode(tempNode, header);
00172                                 }
00173 
00174                         }
00175 
00176                         btreenode.nbKey = this.minKey;
00177                         colFile.writeNode(btreenode, header);
00178                         String newkey = btreenode.getKeyAtPos(i1);
00179                         long keyptr = btreenode.getNodePtrAtPos(i1);
00180 
00181                         StringNode parentNode = (StringNode) colFile.readNode(btreenode.parentPtr);
00182                         SearchResult searchResult1 = parentNode.searchNode(newkey, searchResult);
00183                         flag = parentNode.promote(newkey, keyptr, searchResult1.pos, btreenode1.filePtr);
00184                         colFile.writeNode(parentNode, header);
00185 
00186                 }
00187                 colFile.writeNode(btreenode, header);
00188 
00189                 if (!flag)
00190                         return;
00191 
00192                 // work on root
00193                 root = (StringNode) this.readRoot();
00194                 StringNode parent = new StringNode(header.descriptor.getOrder(),keylength);
00195                 colFile.writeNode(parent, header);
00196                 int j1 = this.minKey;
00197                 StringNode btreenode2 = new StringNode(header.descriptor.getOrder(), keylength);
00198                 btreenode2.parentPtr = parent.filePtr;
00199                 int k;
00200                 for (k = j1 + 1; k < btreenode2.getMaxNbKey(); k++) {
00201                         btreenode2.setKeyPtrAtPos(root.getKeyAtPos(k), root.getNodePtrAtPos(k), k - j1 - 1);
00202                         btreenode2.branchs[k - j1 - 1] = root.branchs[k];
00203                 }
00204 
00205                 btreenode2.branchs[k - j1 - 1] = root.branchs[k];
00206                 btreenode2.nbKey = btreenode2.getMaxNbKey() - j1 - 1;
00207                 colFile.writeNode(btreenode2, header);
00208                 if (btreenode2.branchs[0] != Node.NO_NODE) {
00209                         for (int l = 0; l <= btreenode2.nbKey; l++) {
00210                                 StringNode tempNode = (StringNode) colFile.readNode(btreenode2.branchs[l]);
00211                                 tempNode.parentPtr = btreenode2.filePtr;
00212                                 colFile.writeNode(tempNode, header);
00213                         }
00214                 }
00215                 root.nbKey = this.minKey;
00216                 root.parentPtr = parent.filePtr;
00217                 colFile.writeNode(root, header);
00218                 parent.nbKey = 1;
00219                 parent.setKeyPtrAtPos(root.getKeyAtPos(j1), root.getNodePtrAtPos(j1), 0);
00220                 parent.branchs[0] = root.filePtr;
00221                 parent.branchs[1] = btreenode2.filePtr;
00222                 colFile.writeNode(parent, header);
00223                 return;
00224   }
00225 
00226   //-------------------------
00227   // private utility methods
00228   //-------------------------
00229 
00230 
00231         // find a node
00232         private SearchResult search(StringNode node, String key, SearchResult searchResult) throws IOException, ClassNotFoundException {
00233                 int pos = 0;
00234 
00235                 if (node.nbKey == 0) {
00236                         searchResult.found = false;
00237                         searchResult.node = node;
00238                         searchResult.pos = pos;
00239                         return searchResult;
00240                 }
00241                 searchResult = node.searchNode(key, searchResult);
00242                 if (searchResult.found)
00243                         return searchResult;
00244                 if (searchResult.node.branchs[0] == Node.NO_NODE) {
00245                         return searchResult;
00246                 } else {
00247                         StringNode newNode = (StringNode) colFile.readNode(node.branchs[searchResult.pos]);
00248                         //verify parent ptr of the node
00249                         if (newNode.parentPtr != node.filePtr) {
00250                                 LogManager.traceError(0, "ERROR BAD NODE PARENT");
00251                         }
00252                         searchResult = this.search(newNode, key, searchResult);
00253                         return searchResult;
00254                 }
00255 
00256         }
00257         
00258         public SearchResult getNodeForKey(Object key) throws FODBException      {
00259                 try     {
00260                         StringNode root = (StringNode) this.readRoot();
00261                         SearchResult searchResult = new SearchResult();
00262                         searchResult = this.search(root, (String)key, searchResult);
00263                         return searchResult;            
00264                 } catch (Throwable ex)  {
00265                         throw new FODBException(ex);
00266                 }               
00267         }
00268         
00269 
00270         public long[] query(SodaIndexComparator comparator) throws FODBQueryException {
00271                 try     {
00272                         // find record
00273                         LongArray array = new LongArray(15);
00274                         StringNode root = (StringNode) this.readRoot();
00275                         switch (comparator.getSearchAlgo())     {
00276                                 case SodaIndexComparator.INF_EQUALS_TRAVERSAL :
00277                                         this.searchLikeInfEquals(root, array, (SodaStringIndexComparator)comparator);
00278                                         break;
00279                                 case SodaIndexComparator.SUP_EQUALS_TRAVERSAL :
00280                                         this.searchLikeSupEquals(root, array, (SodaStringIndexComparator)comparator);
00281                                         break;
00282                                 case SodaIndexComparator.FULL_TRAVERSAL :
00283                                         this.searchLikeFull(root, array, (SodaStringIndexComparator)comparator);
00284                                         break;
00285                                 default :
00286                                         break;
00287                         }
00288                         
00289         
00290                         int size = array.size();
00291         
00292                         if (size == 0) {
00293                                 return new long[0];
00294                         }
00295         
00296                         return array.toArray();
00297                 } catch (Throwable ex)  {
00298                         throw new FODBQueryException(ex);
00299                 }
00300         }
00301 
00302         // find a node
00303         private void searchLikeInfEquals(StringNode node, LongArray array, SodaStringIndexComparator comparator) throws IOException, ClassNotFoundException {
00304                 int pos = 0;
00305 
00306                 if (node.nbKey == 0) {
00307                         return;
00308                 }
00309 
00310                 while (true) {
00311                         if (pos == node.nbKey)
00312                                 break;
00313                         if (comparator.isSelected(node.getKeyAtPos(pos))) {
00314                                 addSearchResult(node, pos, array, comparator);
00315                                 if (node.branchs[pos] != Node.NO_NODE) {
00316                                         searchLikeInfEquals((StringNode)colFile.readNode(node.branchs[pos]), array, comparator);
00317                                 }
00318                                 ++pos;
00319                         } else {
00320                                 int comp = comparator.compareTo(node.getKeyAtPos(pos));
00321                                 if (comp < 0)
00322                                         ++pos;
00323                                 else
00324                                         break;
00325                         }
00326                 }
00327 
00328                 if (node.branchs[pos] == Node.NO_NODE) {
00329                         return;
00330                 } else {
00331                         searchLikeInfEquals((StringNode)colFile.readNode(node.branchs[pos]), array, comparator);
00332                 }
00333         }
00334 
00335         // find a node
00336         private void searchLikeSupEquals(StringNode node, LongArray array, SodaStringIndexComparator comparator) throws IOException, ClassNotFoundException {
00337                 int pos = node.nbKey;  //begin at last key
00338 
00339                 if (node.nbKey == 0) {
00340                         return;
00341                 }
00342 
00343                 while (true) {
00344                         if (pos == 0)
00345                                 break;
00346                         if (comparator.isSelected(node.getKeyAtPos(pos-1))) {
00347                                 addSearchResult(node, pos-1, array, comparator);
00348                                 if (node.branchs[pos] != Node.NO_NODE) {
00349                                         searchLikeSupEquals((StringNode)colFile.readNode(node.branchs[pos]), array, comparator);
00350                                 }
00351                                 --pos;
00352                         } else {
00353                                 int comp = comparator.compareTo(node.getKeyAtPos(pos-1));
00354                                 if (comp < 0)
00355                                         --pos;
00356                                 else
00357                                         break;
00358                         }
00359                 }
00360 
00361                 if (node.branchs[pos] == Node.NO_NODE) {
00362                         return;
00363                 } else {
00364                         searchLikeSupEquals((StringNode)colFile.readNode(node.branchs[pos]), array, comparator);
00365                 }
00366         }
00367 
00368         private void searchLikeFull(StringNode pg, LongArray array, SodaStringIndexComparator comparator) throws IOException, ClassNotFoundException {
00369                 int pos = 0;
00370 
00371                 if (pg.nbKey == 0) {
00372                         return;
00373                 }
00374 
00375                 while (true) {
00376                         if (pos == pg.nbKey) {
00377                                 break;
00378                         }
00379                         if (comparator.isSelected(pg.getKeyAtPos(pos))) {
00380                                 addSearchResult(pg, pos, array, comparator);
00381                         }
00382 
00383                         if (pg.branchs[pos] != Node.NO_NODE) {
00384                                 searchLikeFull((StringNode) colFile.readNode(pg.branchs[pos]), array, comparator);
00385                         }
00386 
00387                         ++pos;
00388                 }
00389 
00390                 if (pg.branchs[pos] == Node.NO_NODE) {
00391                         return;
00392                 } else {
00393                         searchLikeFull((StringNode) colFile.readNode(pg.branchs[pos]), array, comparator);
00394                 }
00395         }       
00396         
00397 
00398   protected void parcours(StringNode pg, int level) throws IOException, ClassNotFoundException {
00399     int pos = 0;
00400 
00401     if (pg.nbKey == 0)
00402       return;
00403 
00404     while (true) {
00405       if (pos == pg.nbKey)
00406         break;
00407 
00408       if (pg.branchs[pos] != Node.NO_NODE) {
00409         parcours((StringNode) colFile.readNode(pg.getNodePtrAtPos(pos)), level + 1);
00410       }
00411 
00412       System.out.println("--> " + level + " : " + pg.getKeyAtPos(pos));
00413 
00414       ++pos;
00415     }
00416 
00417     if (pg.branchs[pos] == Node.NO_NODE) {
00418       return;
00419     } else {
00420       parcours((StringNode) colFile.readNode(pg.getNodePtrAtPos(pos)), level + 1);
00421     }
00422     return;
00423   }
00424   
00425 
00426   protected boolean deleteKey(Object keyTodelete, long dbptr) throws IOException, ClassNotFoundException, FODBException {
00427     String key = (String) keyTodelete;
00428 //    System.out.println("" + header.name + " delete : " + key);
00429 
00430     if (key == null) {
00431       return false;
00432     }
00433     if (key.length() == 0) {
00434       return false;
00435     }
00436 
00437     int keylength = ((FODBStringIndexDescriptor)header.descriptor).getKeyLen();
00438     if (key.length() > keylength) {
00439       key = key.substring(0, keylength);
00440     }
00441 
00442                 StringNode root = (StringNode) this.readRoot();
00443                 SearchResult searchResult = new SearchResult();
00444                 searchResult = this.search(root, key, searchResult);
00445                 if (!searchResult.found) {
00446                         return false;
00447                 }
00448                 boolean empty = this.removeKeyPtr(searchResult.node, searchResult.pos, dbptr);
00449                 if (!empty) {
00450                         return true;
00451                 }
00452 
00453                 StringNode btreenode = (StringNode) searchResult.node;
00454                 if (btreenode.branchs[0] != Node.NO_NODE) { //swap key until we find a leaf.
00455                         btreenode = (StringNode) colFile.readNode(btreenode.branchs[searchResult.pos + 1]);
00456                         while (btreenode.branchs[0] != Node.NO_NODE) {
00457                                 btreenode = (StringNode) colFile.readNode(btreenode.branchs[0]);
00458                         }
00459                         StringNode resultNode = (StringNode) searchResult.node;
00460                         resultNode.setKeyPtrAtPos(btreenode.getKeyAtPos(0), btreenode.getNodePtrAtPos(0), searchResult.pos);
00461                         colFile.writeNode(resultNode, header);
00462                         searchResult.node = btreenode; // work on the leaf.
00463                         searchResult.pos = 0;
00464                 }
00465                 btreenode.removeKeyAtPpos(searchResult.pos);
00466                 colFile.writeNode(btreenode,header);
00467                 for (boolean flag = btreenode.nbKey < this.minKey; flag && (btreenode.parentPtr != Node.NO_NODE); flag = btreenode.nbKey < this.minKey) {
00468                         //get the node branch index in parent.
00469                         int i = 0;
00470                         StringNode parentNode = (StringNode) colFile.readNode(btreenode.parentPtr);
00471                         for (i = 0; parentNode.branchs[i] != btreenode.filePtr; i++);
00472                         this.restore(parentNode, i);
00473                         btreenode = parentNode;
00474                 }
00475 
00476                 if (btreenode.parentPtr != Node.NO_NODE)
00477                         return true;
00478                 if (btreenode.nbKey > 0)
00479                         return true;
00480 
00481                 if (btreenode.branchs[0] != Node.NO_NODE) {
00482                         StringNode firstChild = (StringNode) colFile.readNode(root.branchs[0]);
00483                         if (firstChild.nbKey > 0) {
00484                                 firstChild.parentPtr = Node.NO_NODE;
00485                                 colFile.writeNode(firstChild, header);
00486                                 colFile.deleteNode(btreenode);
00487                                 return true;
00488                         }
00489                 }
00490                 return true;
00491   }
00492 
00493   // BTREE Manipulation method
00494 
00495   private void moveLeft(StringNode node, int i) throws IOException, ClassNotFoundException {
00496     StringNode btreenode = (StringNode) colFile.readNode(node.branchs[i]);
00497     btreenode.nbKey++;
00498     btreenode.setKeyPtrAtPos(node.getKeyAtPos(i), node.getNodePtrAtPos(i), btreenode.nbKey - 1);
00499     StringNode branch = (StringNode) colFile.readNode(node.branchs[i + 1]);
00500     btreenode.branchs[btreenode.nbKey] = branch.branchs[0];
00501     colFile.writeNode(btreenode, header);
00502     if (btreenode.branchs[btreenode.nbKey] != Node.NO_NODE) {
00503       StringNode tempNode = (StringNode) colFile.readNode(btreenode.branchs[btreenode.nbKey]); //non passé
00504       tempNode.parentPtr = btreenode.filePtr;
00505       colFile.writeNode(tempNode, header);
00506     }
00507     btreenode = branch;
00508     node.setKeyPtrAtPos(btreenode.getKeyAtPos(0), btreenode.getNodePtrAtPos(0), i);
00509     colFile.writeNode(node, header);
00510 
00511     for (int j = 0; j < btreenode.nbKey - 1; j++) {
00512       btreenode.setKeyPtrAtPos(btreenode.getKeyAtPos(j + 1), btreenode.getNodePtrAtPos(j + 1), j);
00513       btreenode.branchs[j] = btreenode.branchs[j + 1];
00514     }
00515 
00516     btreenode.branchs[btreenode.nbKey - 1] = btreenode.branchs[btreenode.nbKey];
00517     btreenode.nbKey--;
00518     colFile.writeNode(btreenode, header);
00519   }
00520 
00521   private void moveRight(StringNode node, int pos) throws IOException, ClassNotFoundException {
00522     StringNode rightBranch = (StringNode) colFile.readNode(node.branchs[pos + 1]);
00523     rightBranch.branchs[rightBranch.nbKey + 1] = rightBranch.branchs[rightBranch.nbKey];
00524     for (int j = rightBranch.nbKey - 1; j >= 0; j--) {
00525       rightBranch.setKeyPtrAtPos(rightBranch.getKeyAtPos(j), rightBranch.getNodePtrAtPos(j), j + 1);
00526       rightBranch.branchs[j + 1] = rightBranch.branchs[j];
00527     }
00528 
00529     rightBranch.nbKey++;
00530     rightBranch.setKeyPtrAtPos(node.getKeyAtPos(pos), node.getNodePtrAtPos(pos), 0);
00531     StringNode leftBranch = (StringNode) colFile.readNode(node.branchs[pos]);
00532     node.setKeyPtrAtPos(leftBranch.getKeyAtPos(leftBranch.nbKey - 1), leftBranch.getNodePtrAtPos(leftBranch.nbKey - 1), pos);
00533     rightBranch.branchs[0] = leftBranch.branchs[leftBranch.nbKey]; //change child parent ptr.
00534     colFile.writeNode(rightBranch, header);
00535     if (rightBranch.branchs[0] != Node.NO_NODE) {
00536       StringNode tempNode = (StringNode) colFile.readNode(rightBranch.branchs[0]);
00537       tempNode.parentPtr = rightBranch.filePtr;
00538       colFile.writeNode(tempNode, header);
00539     }
00540 
00541     leftBranch.nbKey--;
00542     colFile.writeNode(leftBranch, header);
00543     colFile.writeNode(node, header);
00544   }
00545 
00546   private void combine(StringNode node, int pos) throws IOException, ClassNotFoundException {
00547     StringNode rightBranch = (StringNode) colFile.readNode(node.branchs[pos + 1]);
00548     StringNode leftBranch = (StringNode) colFile.readNode(node.branchs[pos]);
00549     leftBranch.nbKey++;
00550     leftBranch.setKeyPtrAtPos(node.getKeyAtPos(pos), node.getNodePtrAtPos(pos), leftBranch.nbKey - 1);
00551     leftBranch.branchs[leftBranch.nbKey] = rightBranch.branchs[0];
00552     for (int j = 0; j < rightBranch.nbKey; j++) {
00553       leftBranch.nbKey++;
00554       leftBranch.setKeyPtrAtPos(rightBranch.getKeyAtPos(j), rightBranch.getNodePtrAtPos(j), leftBranch.nbKey - 1);
00555       leftBranch.branchs[leftBranch.nbKey] = rightBranch.branchs[j + 1];
00556     }
00557 
00558                 colFile.writeNode(leftBranch, header);
00559     if (leftBranch.branchs[0] != Node.NO_NODE) {
00560       for (int k = 0; k <= leftBranch.nbKey; k++) {
00561         StringNode tempNode = (StringNode) colFile.readNode(leftBranch.branchs[k]); //non passé
00562         tempNode.parentPtr = leftBranch.filePtr;
00563                                 colFile.writeNode(tempNode, header);
00564       }
00565     }
00566 
00567     node.removeKeyAtPpos(pos);
00568                 colFile.writeNode(node, header);
00569                 colFile.deleteNode(rightBranch);
00570   }
00571 
00572   private void restore(StringNode node, int pos) throws IOException, ClassNotFoundException {
00573     if (pos == 0) {
00574       StringNode child = (StringNode) colFile.readNode(node.branchs[1]);
00575       if (child.nbKey > this.minKey) {
00576         this.moveLeft(node, 0);
00577       } else {
00578         this.combine(node, 0);
00579       }
00580     } else if (pos == node.nbKey) {
00581       StringNode child = (StringNode) colFile.readNode(node.branchs[pos - 1]);
00582       if (child.nbKey > this.minKey) {
00583         moveRight(node, pos - 1);
00584       } else {
00585         combine(node, pos - 1);
00586       }
00587     } else {
00588       StringNode childleft = (StringNode) colFile.readNode(node.branchs[pos - 1]);
00589       StringNode childrigth = (StringNode) colFile.readNode(node.branchs[pos + 1]);
00590       if (childleft.nbKey > this.minKey) {
00591         moveRight(node, pos - 1);
00592       } else if (childrigth.nbKey > this.minKey) {
00593         moveLeft(node, pos);
00594       } else {
00595         combine(node, pos);
00596       }
00597     }
00598   }
00599   public org.openmobileis.common.util.collection.Array getArrayKey(Object obj) throws FODBException{
00600         org.openmobileis.common.util.collection.Array keys=new org.openmobileis.common.util.collection.Array();
00601         String key;
00602         String[] keyArray;
00603         boolean isCaseSensitive = ((FODBStringIndexDescriptor)this.getIndexDescriptor()).isCaseSensitive();
00604         if (accessObj instanceof Method) {
00605         try {
00606                 keyArray=(String[])((Method) accessObj).invoke(obj,new Object[0]);
00607                 for(int i=0;i<keyArray.length;i++){
00608                         key=keyArray[i];
00609                         if(key!=null){
00610                                 if (!isCaseSensitive){
00611                                         key=(StringFormater.removeAccent(key).toUpperCase());
00612                                 }
00613                                 keys.add(key);
00614                         }
00615                 }
00616         }catch (InvocationTargetException ex) { 
00617           throw new FODBException("Unable to execute index's method", ex);
00618         } catch (IllegalAccessException ex) { 
00619           throw new FODBException("Unable to execute index's method", ex);
00620         }
00621       }else {
00622         try {
00623                 keyArray=(String[])(((Field) accessObj).get(obj));
00624                 for(int i=0;i<keyArray.length;i++){
00625                         key=keyArray[i];
00626                         if(key!=null){
00627                                 if (!isCaseSensitive){
00628                                         key=(StringFormater.removeAccent(key).toUpperCase());
00629                                 }
00630                                 keys.add(key);
00631                         }
00632                 }
00633         } catch (IllegalAccessException ex) { 
00634           throw new FODBException("Unable to access index's field", ex);
00635         }
00636       }
00637         return keys;
00638   }
00639   protected abstract void writeKeyPtr(Node pg, int pos, long newptr) throws IOException, ClassNotFoundException;
00640   protected abstract void addSearchResult(StringNode pg, int pos, LongArray array, SodaStringIndexComparator comparator) throws IOException, ClassNotFoundException;
00641  // protected abstract void addSearchResult(long pos, LongArray array) throws IOException, ClassNotFoundException;
00642 
00643   protected abstract boolean removeKeyPtr(Node pg, int pos, long pointer) throws IOException, ClassNotFoundException;
00644 }

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