/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (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.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.dynamo.db;

import java.security.Principal;
import java.util.*;
import org.w3c.dom.*;
import com.silverwrist.util.image.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;

public class ImageStoreObject implements NamedObject, ComponentInitialize, ComponentShutdown, ImageStore
{
  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private String m_name;                                    // object name
  private NamespaceCache m_ns_cache;                        // namespace cache object
  private ImageStoreOps m_ops;                              // image store operations
  private Hashtable m_imagetype_tlb = new Hashtable();      // translates imagetypes
  private Hashtable m_imagetype_rev_tlb = new Hashtable();  // translates imagetypes

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  public ImageStoreObject()
  { // do nothing
  } // end constructor

  /*--------------------------------------------------------------------------------
   * Internal operations
   *--------------------------------------------------------------------------------
   */

  private final int imageTypeToIndex(PropertyKey pkey) throws DatabaseException
  {
    Integer foo = (Integer)(m_imagetype_tlb.get(pkey));
    if (foo!=null)
      return foo.intValue();

    int rc = m_ops.imageTypeToIndex(pkey);
    foo = new Integer(rc);
    m_imagetype_tlb.put(pkey,foo);
    m_imagetype_rev_tlb.put(foo,pkey);
    return rc;

  } // end imageTypeToIndex

  private final int imageTypeToIndex(int nsid, String name) throws DatabaseException
  {
    return imageTypeToIndex(new PropertyKey(nsid,name));

  } // end imageTypeToIndex

  private final int imageTypeToIndex(String namespace, String name) throws DatabaseException
  {
    return imageTypeToIndex(new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name));

  } // end imageTypeToIndex

  /*--------------------------------------------------------------------------------
   * Implementations from interface NamedObject
   *--------------------------------------------------------------------------------
   */

  public String getName()
  {
    return m_name;

  } // end getName

  /*--------------------------------------------------------------------------------
   * Implementations from interface ComponentInitialize
   *--------------------------------------------------------------------------------
   */

  public void initialize(Element config_root, ServiceProvider services) throws ConfigException
  {
    String conn_name = null;
    String nscache_name = null;
    XMLLoader loader = XMLLoader.get();
    try
    { // verify the right node name
      loader.verifyNodeName(config_root,"object");

      // get the object's name
      m_name = loader.getAttribute(config_root,"name");

      // get the database configuration connection
      DOMElementHelper config_root_h = new DOMElementHelper(config_root);
      Element elt = loader.getSubElement(config_root_h,"database");
      conn_name = loader.getAttribute(elt,"connection");
      nscache_name = loader.getAttribute(elt,"namespaces");

    } // end try
    catch (XMLLoadException e)
    { // error loading XML config data
      throw new ConfigException(e);

    } // end catch

    // Get the database connection pool and namespace cache.
    DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services,conn_name);
    m_ns_cache =
        (NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name));

    // Get the operations object.
    m_ops = ImageStoreOps.get(pool);

  } // end initialize

  /*--------------------------------------------------------------------------------
   * Implementations from interface ComponentShutdown
   *--------------------------------------------------------------------------------
   */

  public void shutdown()
  {
    m_ops.dispose();
    m_ops = null;
    m_ns_cache = null;

  } // end shutdown

  /*--------------------------------------------------------------------------------
   * Implementations from interface ImageStore
   *--------------------------------------------------------------------------------
   */

  public DataItem getImage(int id) throws DatabaseException
  {
    return m_ops.getImage(id);

  } // end getImage

  public int saveNewImage(String type_namespace, String type_name, Principal owner, DataItem image)
      throws DatabaseException
  {
    int image_type = imageTypeToIndex(type_namespace,type_name);
    int owner_id = 0, owner_flag = 0;
    if (owner instanceof DynamoUser)
      owner_id = ((DynamoUser)owner).getUID();
    else if (owner instanceof DynamoGroup)
    { // get the GID
      owner_id = ((DynamoGroup)owner).getGID();
      owner_flag = 1;

    } // end else if
    else
      throw new DatabaseException(ImageStoreObject.class,"DatabaseMessages","img.badOwner");

    // call down to the database to save it all off
    return m_ops.saveNewImage(image_type,owner_id,owner_flag,image);

  } // end saveNewImage

  public void replaceImage(DynamoUser caller, int image_id, DataItem image)
      throws DatabaseException, DynamoSecurityException
  {
    if (m_ops.canReplaceImage(caller.getUID(),image_id))
      m_ops.replaceImage(image_id,image);
    else
    { // throw a security exception here
      DynamoSecurityException dse = new DynamoSecurityException(ImageStoreObject.class,"DatabaseMessages",
								"img.notOwner");
      dse.setParameter(0,String.valueOf(image_id));
      throw dse;

    } // end else

  } // end replaceImage

  public int findImageID(String type_namespace, String type_name, Principal owner) throws DatabaseException
  {
    int image_type = imageTypeToIndex(type_namespace,type_name);
    int owner_id = 0, owner_flag = 0;
    if (owner instanceof DynamoUser)
      owner_id = ((DynamoUser)owner).getUID();
    else if (owner instanceof DynamoGroup)
    { // get the GID
      owner_id = ((DynamoGroup)owner).getGID();
      owner_flag = 1;

    } // end else if
    else
      throw new DatabaseException(ImageStoreObject.class,"DatabaseMessages","img.badOwner");

    // call down to find it
    return m_ops.findImageID(image_type,owner_id,owner_flag);

  } // end findImageID

  public void deleteImage(DynamoUser caller, int image_id) throws DatabaseException, DynamoSecurityException
  {
    if (m_ops.canReplaceImage(caller.getUID(),image_id))
      m_ops.deleteImage(image_id);
    else
    { // throw a security exception here
      DynamoSecurityException dse = new DynamoSecurityException(ImageStoreObject.class,"DatabaseMessages",
								"img.notOwner");
      dse.setParameter(0,String.valueOf(image_id));
      throw dse;

    } // end else

  } // end deleteImage

  public DataItem normalizeImage(DataItem source, int width, int height, String new_type) throws Exception
  {
    try
    { // normalize the image and encapsulate it in a StaticDataItem
      byte[] data = ImageNormalizer.normalizeImage(source.getDataStream(),width,height,new_type);
      return new StaticDataItem(source.getName() + "-converted",new_type,data.length,data);

    } // end try
    catch (ImageNormalizerException e)
    { // morph the exception
      ExternalException ee = new ExternalException(ImageStoreObject.class,"DatabaseMessages",
						   "img.normalize",e);
      ee.setParameter(0,source.getName());
      ee.setParameter(1,e.getMessage());
      throw ee;

    } // end catch

  } // end normalizeImage

} // end class ImageStoreObject
