/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.cache.loader;

import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCache;
import org.jboss.system.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Properties;

/**
 * Implementations need to load an object given a key from secondary storage, or store an object under a given
 * key in secondary storage (e.g. DB, filesystem).<br/>
 * Lifecycle: first an instance of the loader is created, then the configuration ({@link #setConfig(String)})
 * and cache ({@link #setCache(TreeCache)}) are set. After this, {@link #create()} is called. Then {@link @start()} is
 * called. When re-deployed, {@link #stop()} will be called, followed by another {@link #start()}. Finally, when
 * shut down, {@link #destroy()} is called, after which the loader is unusable.
 *
 * @author Bela Ban Oct 31, 2003
 * @version $Id: CacheLoader.java,v 1.1.2.7 2005/12/01 19:48:41 dimitris Exp $
 */
public interface CacheLoader extends Service {


   /**
    * Sets the configuration. Will be called before {@link #create()} and {@link #start()}
    * @param url A list of properties, defined in the XML file
    */
   void setConfig(Properties url);


   /**
    * This method allows the CacheLoader to set the TreeCache, therefore allowing the CacheLoader to invoke
    * methods of the TreeCache. It can also use the TreeCache to fetch configuration information. Alternatively,
    * the CacheLoader could maintain its own configuration<br/>
    * This method will be called directly after the CacheLoader instance has been created
    * @param c The cache on which this loader works
    */
   void setCache(TreeCache c);


   /**
    * Returns a list of children names, all names are <em>relative</em>. Returns null if the parent node is not found.
    * The returned set must not be modified, e.g. use Collections.unmodifiableSet(s) to return the result
    * @param fqn The FQN of the parent
    * @return Set<String>. A list of children. Returns null if no children nodes are present, or the parent is
    * not present
    */
   Set getChildrenNames(Fqn fqn) throws Exception;


   /**
    * Returns the value for a given key. Returns null if the node doesn't exist, or the value is not bound
    * @param name
    * @return
    * @throws Exception
    */
   Object get(Fqn name, Object key) throws Exception;


   /**
    * Returns all keys and values from the persistent store, given a fully qualified name
    * @param name
    * @return Map<Object,Object> of keys and values for the given node. Returns null if the node was not found, or
    * if the node has no attributes
    * @throws Exception
    */
   Map get(Fqn name) throws Exception;


   /**
    * Checks whether the CacheLoader has a node with Fqn
    * @param name
    * @return True if node exists, false otherwise
    */
   boolean exists(Fqn name) throws Exception;


   /**
    * Inserts key and value into the attributes hashmap of the given node. If the node does not exist, all
    * parent nodes from the root down are created automatically. Returns the old value
    */
   Object put(Fqn name, Object key, Object value) throws Exception;

   /**
    * Inserts all elements of attributes into the attributes hashmap of the given node, overwriting existing
    * attributes, but not clearing the existing hashmap before insertion (making it a union of existing and
    * new attributes)
    * If the node does not exist, all parent nodes from the root down are created automatically
    * @param name The fully qualified name of the node
    * @param attributes A Map of attributes. Can be null
    */
   void put(Fqn name, Map attributes) throws Exception;



   /**
    * Inserts all modifications to the backend store. Overwrite whatever is already in
    * the datastore.
    * @param modifications A List<Modification> of modifications
    * @throws Exception
    */
   void put(List modifications) throws Exception;


   /**
    * Removes the given key and value from the attributes of the given node. No-op if node doesn't exist
    */
   Object remove(Fqn name, Object key) throws Exception;

   /**
    * Removes the given node. If the node is the root of a subtree, this will recursively remove all subnodes,
    * depth-first
    */
   void remove(Fqn name) throws Exception;


   /**
    * Removes all attributes from a given node, but doesn't delete the node itself
    * @param name
    * @throws Exception
    */
   void removeData(Fqn name) throws Exception;


   /**
    * Prepare the modifications. For example, for a DB-based CacheLoader:
    * <ol>
    * <li>Create a local (JDBC) transaction
    * <li>Associate the local transaction with <code>tx</code> (tx is the key)
    * <li>Execute the coresponding SQL statements against the DB (statements derived from modifications)
    * </ol>
    * For non-transactional CacheLoader (e.g. file-based), this could be a null operation
    *
    * @param tx            The transaction, just used as a hashmap key
    * @param modifications List<Modification>, a list of all modifications within the given transaction
    * @param one_phase     Persist immediately and (for example) commit the local JDBC transaction as well. When true,
    *                      we won't get a {@link #commit(Object)} or {@link #rollback(Object)} method call later
    * @throws Exception
    */
   void prepare(Object tx, List modifications, boolean one_phase) throws Exception;

   /**
    * Commit the transaction. A DB-based CacheLoader would look up the local JDBC transaction asociated
    * with <code>tx</code> and commit that transaction<br/>
    * Non-transactional CacheLoaders could simply write the data that was previously saved transiently under the
    * given <code>tx</code> key, to (for example) a file system (note this only holds if the previous prepare() did
    * not define one_phase=true
    *
    * @param tx
    */
   void commit(Object tx) throws Exception;

   /**
    * Roll the transaction back. A DB-based CacheLoader would look up the local JDBC transaction asociated
    * with <code>tx</code> and roll back that transaction
    *
    * @param tx
    */
   void rollback(Object tx);


   /**
    * Fetch the entire state for this cache from secondary storage (disk, DB) and return it as a byte buffer.
    * This is for initialization of a new cache from a remote cache. The new cache would then call
    * storeEntireState().<br/>
    * todo: define binary format for exchanging state
    */
   byte[] loadEntireState() throws Exception;

   /**
    * Store the given state in secondary storage. Overwrite whatever is currently in seconday storage.
    */
   void storeEntireState(byte[] state) throws Exception;

}
