ozeigermann    2004/10/19 04:47:06

  Modified:    src/share/org/apache/slide/store AbstractStore.java
                        Store.java ExtendedStore.java
               src/share/org/apache/slide/macro MacroImpl.java
               src/share/org/apache/slide/common Namespace.java
  Added:       src/share/org/apache/slide/store MacroStore.java
  Log:
  Initial support for macro store.
  When configured store supports the MacroStore interface 
MacroImpl
  will forward the request to the store level. ExtendedStore will invalidate
  caches of delete and moved resources.
  
  TODO:
  - Add real check if move/copy/delete is inside a single store
  - Add security check
  - Add lock check
  
  Revision  Changes    Path
  1.45      +87 -5     
jakarta-slide/src/share/org/apache/slide/store/AbstractStore.java
  
  Index: AbstractStore.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/share/org/apache/slide/store/AbstractStore.java,v
  retrieving revision 1.44
  retrieving revision 1.45
  diff -u -r1.44 -r1.45
  --- AbstractStore.java        18 Oct 2004 09:18:30 -0000      1.44
  +++ AbstractStore.java        19 Oct 2004 11:47:05 -0000      1.45
  @@ -127,6 +127,11 @@
       protected SequenceStore sequenceStore = null;
       
       /**
  +     * Macro store
  +     */
  +    protected MacroStore macroStore = null;
  +    
  +    /**
        * Active resource manager list.
        */
       protected Service resourceManagers[] = new Service[0];
  @@ -531,12 +536,19 @@
       }
       
       /**
  -     * Set the sequence store associated with this store.
  +     * Sets the sequence store associated with this store.
        */
       public void setSequenceStore(SequenceStore store) {
           sequenceStore = store;
       }
           
  +    /**
  +     * Sets the sequence store associated with this store.
  +     */
  +    public void setMacroStore(MacroStore store) {
  +        macroStore = store;
  +    }
  +        
       //
       // sequence methods 
       //
  @@ -578,6 +590,76 @@
           return sequenceStore.nextSequenceValue(sequenceName);
       }
   
  +    //
  +    // macro methods 
  +    //
  +
  +    /**
  +     * @see org.apache.slide.store.MacroStore#isMacroDeleteSupported()
  +     */
  +    public boolean isMacroDeleteSupported() {
  +        return (macroStore != null && macroStore.isMacroDeleteSupported());
  +    }
  +
  +    /**
  +     * @see 
org.apache.slide.store.MacroStore#macroDelete(org.apache.slide.common.Uri)
  +     */
  +    public void macroDelete(Uri targetUri) throws ServiceAccessException, 
ObjectNotFoundException {
  +        if (!isMacroDeleteSupported()) {
  +            throw new ServiceAccessException(this, "Macro delete not supported");
  +        }
  +        enlist(macroStore);
  +        try {
  +            macroStore.macroDelete(targetUri);
  +        } finally {
  +            delist(macroStore);
  +        }
  +    }
  +
  +    /**
  +     * @see org.apache.slide.store.MacroStore#isMacroCopySupported()
  +     */
  +    public boolean isMacroCopySupported() {
  +        return (macroStore != null && macroStore.isMacroCopySupported());
  +    }
  +
  +    /**
  +     * @see 
org.apache.slide.store.MacroStore#macroCopy(org.apache.slide.common.Uri, 
org.apache.slide.common.Uri)
  +     */
  +    public void macroCopy(Uri sourceUri, Uri targetUri) throws 
ServiceAccessException, ObjectNotFoundException, ObjectAlreadyExistsException {
  +        if (!isMacroCopySupported()) {
  +            throw new ServiceAccessException(this, "Macro copy not supported");
  +        }
  +        enlist(macroStore);
  +        try {
  +            macroStore.macroCopy(sourceUri, targetUri);
  +        } finally {
  +            delist(macroStore);
  +        }
  +    }
  +
  +    /**
  +     * @see org.apache.slide.store.MacroStore#isMacroMoveSupported()
  +     */
  +    public boolean isMacroMoveSupported() {
  +        return (macroStore != null && macroStore.isMacroMoveSupported());
  +    }
  +
  +    /**
  +     * @see 
org.apache.slide.store.MacroStore#macroMove(org.apache.slide.common.Uri, 
org.apache.slide.common.Uri)
  +     */
  +    public void macroMove(Uri sourceUri, Uri targetUri) throws 
ServiceAccessException, ObjectNotFoundException, ObjectAlreadyExistsException {
  +        if (!isMacroMoveSupported()) {
  +            throw new ServiceAccessException(this, "Macro move not supported");
  +        }
  +        enlist(macroStore);
  +        try {
  +            macroStore.macroMove(sourceUri, targetUri);
  +        } finally {
  +            delist(macroStore);
  +        }
  +    }
  +    
       /**
        * Retrive an object from the Descriptors Store.
        *
  
  
  
  1.13      +11 -6     jakarta-slide/src/share/org/apache/slide/store/Store.java
  
  Index: Store.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/Store.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Store.java        28 Jul 2004 09:34:39 -0000      1.12
  +++ Store.java        19 Oct 2004 11:47:05 -0000      1.13
  @@ -31,7 +31,7 @@
    * @version $Revision$
    */
   public interface Store extends ContentStore, LockStore, NodeStore,
  -    RevisionDescriptorStore, RevisionDescriptorsStore, SecurityStore, SequenceStore 
 {
  +    RevisionDescriptorStore, RevisionDescriptorsStore, SecurityStore, 
SequenceStore, MacroStore  {
       
       
       // ------------------------------------------------------ Interface Methods
  @@ -113,9 +113,14 @@
       void setContentIndexer(IndexStore contentStore);
       
       /**
  -     * Sets the sequence store associated with this store.
  +     * Sets the optional sequence store associated with this store.
        */
       void setSequenceStore(SequenceStore sequenceStore);
  +    
  +    /**
  +     * Sets the optional macro store associated with this store.
  +     */
  +    void setMacroStore(MacroStore macroStore);
       
       /**
        * Returns true if binding is supported an enabled for this store
  
  
  
  1.19      +64 -4     
jakarta-slide/src/share/org/apache/slide/store/ExtendedStore.java
  
  Index: ExtendedStore.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/share/org/apache/slide/store/ExtendedStore.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- ExtendedStore.java        9 Aug 2004 22:56:12 -0000       1.18
  +++ ExtendedStore.java        19 Oct 2004 11:47:05 -0000      1.19
  @@ -421,6 +421,35 @@
        }
       }
       
  +    /**
  +     * Removes an object hierarchy from all internal caches.
  +     * 
  +     * @param key
  +     *            the key under which the object is stored in the caches.
  +     */
  +    public void removeObjectHierachyFromCache(Uri folderUri) {
  +        getLogger().log("Removing hierarchy" + folderUri + " from cache.", 
LOG_CHANNEL, Logger.DEBUG);
  +        if (contentStore.cacheResults() && contentCachingEnabled) {
  +            contentCache.remove(folderUri.toString(), "/");
  +        }
  +        if (nodeStore.cacheResults()) {
  +            objectsCache.remove(folderUri.toString(), "/");
  +        }
  +        if (securityStore.cacheResults()) {
  +            permissionsCache.remove(folderUri.toString(), "/");
  +        }
  +        // Locks shouldn't be cached, but just in case.
  +        if (lockStore.cacheResults()) {
  +            locksCache.remove(folderUri.toString(), "/");
  +        }
  +        if (revisionDescriptorsStore.cacheResults()) {
  +            descriptorsCache.remove(folderUri.toString(), "/");
  +        }
  +        if (revisionDescriptorStore.cacheResults()) {
  +            descriptorCache.remove(folderUri.toString(), "/");
  +        }
  +    }
  +    
       public void exclusiveTransientLock(String uri)
                        throws ServiceAccessException {
                Xid txId = (Xid) activeTransactionBranch.get();
  @@ -1316,6 +1345,37 @@
               }
           }
   
  +    }
  +
  +    public void macroDelete(Uri targetUri) throws ServiceAccessException, 
ObjectNotFoundException {
  +        enlist(this);
  +        try {
  +            removeObjectHierachyFromCache(targetUri);
  +        } finally {
  +            delist(this);
  +        }
  +        super.macroDelete(targetUri);
  +    }
  +
  +    public void macroCopy(Uri sourceUri, Uri targetUri) throws 
ServiceAccessException, ObjectNotFoundException, ObjectAlreadyExistsException {
  +        enlist(this);
  +        try {
  +            removeObjectHierachyFromCache(targetUri);
  +        } finally {
  +            delist(this);
  +        }
  +        super.macroCopy(sourceUri, targetUri);
  +    }
  +    
  +    public void macroMove(Uri sourceUri, Uri targetUri) throws 
ServiceAccessException, ObjectNotFoundException, ObjectAlreadyExistsException {
  +        enlist(this);
  +        try {
  +            removeObjectHierachyFromCache(sourceUri);
  +            removeObjectHierachyFromCache(targetUri);
  +        } finally {
  +            delist(this);
  +        }
  +        super.macroMove(sourceUri, targetUri);
       }
   
   }
  
  
  
  1.1                  jakarta-slide/src/share/org/apache/slide/store/MacroStore.java
  
  Index: MacroStore.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-slide/src/share/org/apache/slide/store/MacroStore.java,v 1.1 
2004/10/19 11:47:05 ozeigermann Exp $
   * $Revision: 1.1 $
   * $Date: 2004/10/19 11:47:05 $
   *
   * ====================================================================
   *
   * Copyright 2004 The Apache Software Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   */
  
  package org.apache.slide.store;
  
  import org.apache.slide.common.Service;
  import org.apache.slide.common.ServiceAccessException;
  import org.apache.slide.common.Uri;
  import org.apache.slide.macro.CopyMacroException;
  import org.apache.slide.macro.DeleteMacroException;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.structure.ObjectAlreadyExistsException;
  import org.apache.slide.structure.ObjectNotFoundException;
  
  /**
   * Store for macro opertations support. This store executes compound operations
   * on hierarchical data. A recursive copy, a recursive delete and a recursive
   * move resp. rename are supported provided the [EMAIL PROTECTED] 
#isMacroCopySupported()},
   * [EMAIL PROTECTED] #isMacroMoveSupported()}and/or [EMAIL PROTECTED] 
#isMacroDeleteSupported()}
   * indicate this. By having checks for all three macro opertations stores can
   * dynamically decide which kind of operations they support. E.g. This allows
   * for stores that only support recursive deletes.
   * 
   * @version $Revision: 1.1 $
   */
  public interface MacroStore extends Service {
  
      /**
       * Checks if this store instance actually supports macro delete operation.
       * It may seem clear this store supports sequences as it implements this
       * interface, but a request to the underlying persistence store might be
       * needed to dynamically find out.
       * 
       * @return <code>true</code> if the store supports the macro delete
       *         operation, <code>false</code> otherwise
       */
      public boolean isMacroDeleteSupported();
  
      /**
       * Deletes an object recursively.
       * 
       * @param targetUri
       *            Uri of the object to delete
       * @throws ObjectNotFoundException if the object to delete was not found
       * @throws ServiceAccessException
       *             if anything else goes wrong while deleting the object
       */
      public void macroDelete(Uri targetUri) throws ServiceAccessException, 
ObjectNotFoundException;
  
      /**
       * Checks if this store instance actually supports macro copy operation. It
       * may seem clear this store supports sequences as it implements this
       * interface, but a request to the underlying persistence store might be
       * needed to dynamically find out.
       * 
       * @return <code>true</code> if the store supports the macro copy
       *         operation, <code>false</code> otherwise
       */
      public boolean isMacroCopySupported();
  
      /**
       * Recursively copies an object.
       * 
       * @param sourceUri the source URI of the copy
       * @param targetUri the destination URI of the copy
       * @throws ObjectNotFoundException if the object to copy from was not found
       * @throws ObjectAlreadyExistsException if the object to copy to to was already 
there
       * @throws ServiceAccessException
       *             if anything else goes wrong while copying the object
       */
      public void macroCopy(Uri sourceUri, Uri targetUri) throws 
ServiceAccessException, ObjectNotFoundException,
              ObjectAlreadyExistsException;
  
      /**
       * Checks if this store instance actually supports macro move operation. It
       * may seem clear this store supports sequences as it implements this
       * interface, but a request to the underlying persistence store might be
       * needed to dynamically find out.
       * 
       * @return <code>true</code> if the store supports the macro move
       *         operation, <code>false</code> otherwise
       */
      public boolean isMacroMoveSupported();
  
      /**
       * Recursively moves an object.
       * 
       * @param sourceUri the source URI of the move
       * @param targetUri the destination URI of the move
       * @throws ObjectNotFoundException if the object to move from was not found
       * @throws ObjectAlreadyExistsException if the object to move to to was already 
there
       * @throws ServiceAccessException
       *             if anything else goes wrong while moving the object
       */
      public void macroMove(Uri sourceUri, Uri targetUri) throws 
ServiceAccessException, ObjectNotFoundException,
              ObjectAlreadyExistsException;
  
  }
  
  
  1.44      +123 -34   jakarta-slide/src/share/org/apache/slide/macro/MacroImpl.java
  
  Index: MacroImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/macro/MacroImpl.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- MacroImpl.java    18 Oct 2004 08:52:36 -0000      1.43
  +++ MacroImpl.java    19 Oct 2004 11:47:05 -0000      1.44
  @@ -32,10 +32,12 @@
   import org.apache.slide.common.Domain;
   import org.apache.slide.common.Namespace;
   import org.apache.slide.common.NamespaceConfig;
  +import org.apache.slide.common.Scope;
   import org.apache.slide.common.ServiceAccessException;
   import org.apache.slide.common.SlideException;
   import org.apache.slide.common.SlideToken;
   import org.apache.slide.common.SlideTokenWrapper;
  +import org.apache.slide.common.Uri;
   import org.apache.slide.content.Content;
   import org.apache.slide.content.NodeProperty;
   import org.apache.slide.content.NodeRevisionContent;
  @@ -52,6 +54,7 @@
   import org.apache.slide.security.Security;
   import org.apache.slide.store.Store;
   import org.apache.slide.structure.LinkedObjectNotFoundException;
  +import org.apache.slide.structure.ObjectAlreadyExistsException;
   import org.apache.slide.structure.ObjectHasChildrenException;
   import org.apache.slide.structure.ObjectNode;
   import org.apache.slide.structure.ObjectNotFoundException;
  @@ -200,27 +203,54 @@
               throw e;
           }
           
  -        // try to writeLock the complete destination tree
  -        try {
  -            writeLock(token, destinationUri, true);
  -        }
  -        catch( ServiceAccessException x ) {
  -            e.addException(x);
  -            throw e;
  -        }
  -        catch (SlideException x) {}; // ignore silently
  -        
  -        Map alreadyCopied = new HashMap(); // maps source-UURI -> destination-URI
  -        parameters.setParameter( ALREADY_COPIED, alreadyCopied );
  -        
  -        copyObject(token, sourceUri, destinationUri, parameters, true, e,
  -                   copyRedirector, copyListener, deleteRedirector, deleteListener);
  -        
  -        // If there were errors, we throw the nested exception
  -        if (!e.isEmpty()) {
  -            throw e;
  -        }
  +        Uri source = namespace.getUri(token, sourceUri);
  +        Uri destination = namespace.getUri(token, destinationUri);
  +        Store store = source.getStore();
  +
  +        if (store.isMacroCopySupported() && source.getStore() == 
destination.getStore()
  +                && namespace.canUseMacroStore(source) && 
namespace.canUseMacroStore(destination)) {
  +            try {
  +                store.macroCopy(source, destination);
   
  +                Uri parentUri = destination.getParentUri();
  +                ObjectNode parentNode = 
parentUri.getStore().retrieveObject(parentUri);
  +                
  +                ObjectNode destinationNode = 
destination.getStore().retrieveObject(destination);
  +                parentNode.addChild(destinationNode);
  +                parentUri.getStore().storeObject(parentUri, parentNode);
  +
  +            } catch (ObjectNotFoundException x) {
  +                e.addException(x);
  +                throw e;
  +            } catch (ObjectAlreadyExistsException x) {
  +                e.addException(x);
  +                throw e;
  +            } catch (ServiceAccessException x) {
  +                e.addException(x);
  +                throw e;
  +            }
  +        } else {
  +            // try to writeLock the complete destination tree
  +            try {
  +                writeLock(token, destinationUri, true);
  +            }
  +            catch( ServiceAccessException x ) {
  +                e.addException(x);
  +                throw e;
  +            }
  +            catch (SlideException x) {}; // ignore silently
  +            
  +            Map alreadyCopied = new HashMap(); // maps source-UURI -> 
destination-URI
  +            parameters.setParameter( ALREADY_COPIED, alreadyCopied );
  +            
  +            copyObject(token, sourceUri, destinationUri, parameters, true, e,
  +                       copyRedirector, copyListener, deleteRedirector, 
deleteListener);
  +            
  +            // If there were errors, we throw the nested exception
  +            if (!e.isEmpty()) {
  +                throw e;
  +            }
  +        }
           try {
               if ( MacroEvent.COPY.isEnabled() ) 
EventDispatcher.getInstance().fireVetoableEvent(MacroEvent.COPY, new MacroEvent(this, 
token, namespace, sourceUri, destinationUri));
           } catch ( VetoException ve ) {
  @@ -438,9 +468,47 @@
                      copyRedirector, copyListener, deleteRedirector, deleteListener);
           }
           else {
  -            copy(token, sourceUri, destinationUri, parameters,
  -                 copyRedirector, copyListener, deleteRedirector, deleteListener);
  -            delete(token, sourceUri, parameters, deleteRedirector, deleteListener);
  +            CopyMacroException e = new CopyMacroException("Move failed");
  +            
  +            Uri source = namespace.getUri(token, sourceUri);
  +            Uri destination = namespace.getUri(token, destinationUri);
  +            Store store = source.getStore();
  +
  +            if (store.isMacroMoveSupported() && source.getStore() == 
destination.getStore()
  +                    && namespace.canUseMacroStore(source) && 
namespace.canUseMacroStore(destination)) {
  +                try {
  +
  +                    Uri sourceParentUri = source.getParentUri();
  +                    ObjectNode sourceParentNode = 
sourceParentUri.getStore().retrieveObject(sourceParentUri);
  +                    
  +                    ObjectNode sourceNode = 
source.getStore().retrieveObject(source);
  +                    sourceParentNode.removeChild(sourceNode);
  +                    sourceParentUri.getStore().storeObject(sourceParentUri, 
sourceParentNode);
  +
  +                    store.macroMove(source, destination);
  +
  +                    Uri parentUri = destination.getParentUri();
  +                    ObjectNode parentNode = 
parentUri.getStore().retrieveObject(parentUri);
  +                    
  +                    ObjectNode destinationNode = 
destination.getStore().retrieveObject(destination);
  +                    parentNode.addChild(destinationNode);
  +                    parentUri.getStore().storeObject(parentUri, parentNode);
  +
  +                } catch (ObjectNotFoundException x) {
  +                    e.addException(x);
  +                    throw e;
  +                } catch (ObjectAlreadyExistsException x) {
  +                    e.addException(x);
  +                    throw e;
  +                } catch (ServiceAccessException x) {
  +                    e.addException(x);
  +                    throw e;
  +                }
  +            } else {
  +                copy(token, sourceUri, destinationUri, parameters,
  +                     copyRedirector, copyListener, deleteRedirector, 
deleteListener);
  +                delete(token, sourceUri, parameters, deleteRedirector, 
deleteListener);
  +            }
           }
   
           try {
  @@ -520,20 +588,41 @@
           
           DeleteMacroException e = new DeleteMacroException("Delete failed");
           
  -        deleteObject(token, targetUri, e, deleteRedirector, deleteListener);
  -        
  -        // If there were errors, we throw the nested exception
  -        if (!e.isEmpty()) {
  -            throw e;
  -        }
  +        Uri destination = namespace.getUri(token, targetUri);
  +        Store store = destination.getStore();
   
  +        if (store.isMacroDeleteSupported() && 
namespace.canUseMacroStore(destination)) {
  +            try {
  +                Uri parentUri = destination.getParentUri();
  +                ObjectNode parentNode = 
parentUri.getStore().retrieveObject(parentUri);
  +                
  +                ObjectNode destinationNode = 
destination.getStore().retrieveObject(destination);
  +                parentNode.removeChild(destinationNode);
  +                parentUri.getStore().storeObject(parentUri, parentNode);
  +
  +                store.macroDelete(destination);
  +                
  +            } catch (ObjectNotFoundException x) {
  +                e.addException(x);
  +                throw e;
  +            } catch (ServiceAccessException x) {
  +                e.addException(x);
  +                throw e;
  +            }
  +        } else {
  +            deleteObject(token, targetUri, e, deleteRedirector, deleteListener);
  +            
  +            // If there were errors, we throw the nested exception
  +            if (!e.isEmpty()) {
  +                throw e;
  +            }
  +        }
           try {
               if ( MacroEvent.DELETE.isEnabled() ) 
EventDispatcher.getInstance().fireVetoableEvent(MacroEvent.DELETE, new 
MacroEvent(this, token, namespace, targetUri));
           } catch ( VetoException ve ) {
               throw new DeleteMacroException(ve.getMessage());
           }
       }
  -    
       
       // -------------------------------------------------------- Private Methods
       
  
  
  
  1.70      +19 -4     jakarta-slide/src/share/org/apache/slide/common/Namespace.java
  
  Index: Namespace.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/common/Namespace.java,v
  retrieving revision 1.69
  retrieving revision 1.70
  diff -u -r1.69 -r1.70
  --- Namespace.java    5 Oct 2004 21:19:55 -0000       1.69
  +++ Namespace.java    19 Oct 2004 11:47:06 -0000      1.70
  @@ -41,6 +41,7 @@
   import org.apache.slide.store.DefaultIndexer;
   import org.apache.slide.store.IndexStore;
   import org.apache.slide.store.LockStore;
  +import org.apache.slide.store.MacroStore;
   import org.apache.slide.store.NodeStore;
   import org.apache.slide.store.RevisionDescriptorStore;
   import org.apache.slide.store.RevisionDescriptorsStore;
  @@ -109,6 +110,7 @@
       public static final String PROPERTIES_INDEX_STORE = "propertiesindexer";
       public static final String CONTENT_INDEX_STORE = "contentindexer";
       public static final String SEQUENCE_STORE = "sequencestore";
  +    public static final String MACRO_STORE = "macrostore";
       
       
       /**
  @@ -339,6 +341,10 @@
       
       // --------------------------------------------------------- Public Methods
       
  +    public boolean canUseMacroStore(Uri source) {
  +        // TODO check if all children of this uri are in the same store
  +        return true;
  +    }
       
       /**
        * Used to register a Store in the namespace for the specified scope.
  @@ -435,6 +441,12 @@
                   
                   store.setSequenceStore(sequenceStore);
                   
  +                // assign MacroStore
  +                MacroStore macroStore =
  +                    (MacroStore) dereferenceStore (MACRO_STORE, childStores);
  +                
  +                store.setMacroStore(macroStore);
  +                
                   // set the scope in the father and child stores
                   store.setScope(scope);
                   
  @@ -1005,6 +1017,9 @@
           
           // Loading sequence store (if any)
           getChildStore (storeDefinition, SEQUENCE_STORE, currentStoreChildStores, 
storeParameters);
  +
  +        // Loading macro store (if any)
  +        getChildStore (storeDefinition, MACRO_STORE, currentStoreChildStores, 
storeParameters);
   
           childStores.put(storeName, currentStoreChildStores);
           
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to