package org.dbxml.core.objects;

/*
 * dbXML License, Version 1.0
 *
 *
 * Copyright (c) 1999-2001 The dbXML Group, L.L.C.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by
 *        The dbXML Group (http://www.dbxml.com/)."
 *    Alternately, this acknowledgment may appear in the software
 *    itself, if and wherever such third-party acknowledgments normally
 *    appear.
 *
 * 4. The names "dbXML" and "The dbXML Group" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    info@dbxml.com.
 *
 * 5. Products derived from this software may not be called "dbXML",
 *    nor may "dbXML" appear in their name, without prior written
 *    permission of The dbXML Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE DBXML GROUP OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: Variant.java,v 1.17 2001/05/23 00:35:12 tom Exp $
 */

import org.dbxml.server.*;
import org.dbxml.core.*;
import org.dbxml.xml.*;
import org.dbxml.server.util.*;

import org.w3c.dom.*;

/**
 * Variant is a generic type that can be used to store any type of dbXML
 * variable.  Variants will do their best to convert the value that they
 * store to any requested type.
 */

public final class Variant {
   private Object value = null;
   private int type = -1;

   public Variant() {
   }

   public Variant(Variant value) {
      this.value = value.value;
      type = value.type;
   }

   public Variant(String value) {
      this.value = value;
      type = Types.STRING;
   }

   public Variant(boolean value) {
      this.value = new Boolean(value);
      type = Types.BOOLEAN;
   }

   public Variant(byte value) {
      this.value = new Byte(value);
      type = Types.BYTE;
   }

   public Variant(char value) {
      this.value = new Character(value);
      type = Types.CHAR;
   }

   public Variant(short value) {
      this.value = new Short(value);
      type = Types.SHORT;
   }

   public Variant(int value) {
      this.value = new Integer(value);
      type = Types.INT;
   }

   public Variant(long value) {
      this.value = new Long(value);
      type = Types.LONG;
   }

   public Variant(float value) {
      this.value = new Float(value);
      type = Types.FLOAT;
   }

   public Variant(double value) {
      this.value = new Double(value);
      type = Types.DOUBLE;
   }

   public Variant(Element value) {
      this.value = value;
      type = Types.ELEMENT;
   }

   public Variant(Document value) {
      this.value = value;
      type = Types.DOCUMENT;
   }

   public Variant(DocumentFragment value) {
      this.value = value;
      type = Types.DOCUMENTFRAGMENT;
   }

   public Variant(Args value) {
      this.value = value;
      type = Types.ARGS;
   }

   public Variant(Object value) {
      this.value = value;
      type = Types.OBJECT;
   }

   /**
    * getType returns the type of the variable being stored in the Variant.
    *
    * @return The variable type
    */
   public int getType() {
      return type;
   }

   /**
    * isNull returns whether or not the variable is storing a null value.
    */
   public boolean isNull() {
      return value == null;
   }

   /**
    * set sets the value as a String.
    *
    * @param value The value
    */
   public void set(String value) {
      this.value = value;
      type = Types.STRING;
   }

   /**
    * set sets the value as a boolean.
    *
    * @param value The value
    */
   public void set(boolean value) {
      this.value = new Boolean(value);
      type = Types.BOOLEAN;
   }

   /**
    * set sets the value as a byte.
    *
    * @param value The value
    */
   public void set(byte value) {
      this.value = new Byte(value);
      type = Types.BYTE;
   }

   /**
    * set sets the value as a char.
    *
    * @param value The value
    */
   public void set(char value) {
      this.value = new Character(value);
      type = Types.CHAR;
   }

   /**
    * set sets the value as a short
    *
    * @param value The value
    */
   public void set(short value) {
      this.value = new Short(value);
      type = Types.SHORT;
   }

   /**
    * set sets the value as an int.
    *
    * @param value The value
    */
   public void set(int value) {
      this.value = new Integer(value);
      type = Types.INT;
   }

   /**
    * set sets the value as a long.
    *
    * @param value The value
    */
   public void set(long value) {
      this.value = new Long(value);
      type = Types.LONG;
   }

   /**
    * set sets the value as a float.
    *
    * @param value The value
    */
   public void set(float value) {
      this.value = new Float(value);
      type = Types.FLOAT;
   }

   /**
    * set sets the value as a double.
    *
    * @param value The value
    */
   public void set(double value) {
      this.value = new Double(value);
      type = Types.DOUBLE;
   }

   /**
    * set sets the value as an Element.
    *
    * @param value The value
    */
   public void set(Element value) {
      this.value = value;
      type = Types.ELEMENT;
   }

   /**
    * set sets the value as a Document.
    *
    * @param value The value
    */
   public void set(Document value) {
      this.value = value;
      type = Types.DOCUMENT;
   }

   /**
    * set sets the value as a DocumentFragment.
    *
    * @param value The value
    */
   public void set(DocumentFragment value) {
      this.value = value;
      type = Types.DOCUMENTFRAGMENT;
   }

   /**
    * set sets the value as an Args instance.
    *
    * @param value The value
    */
   public void set(Args value) {
      this.value = value;
      type = Types.ARGS;
   }

   /**
    * set sets the value as an Object.
    *
    * @param value The value
    */
   public void set(Object object) {
      this.value = value;
      type = value != null ? Types.OBJECT
                           : Types.EMPTY;
   }

   /**
    * getString returns the value as a String.
    *
    * @return The value
    */
   public String getString() {
      if ( type == Types.STRING )
         return (String)value;
      else
         return value.toString();
   }

   /**
    * getBoolean returns the value as a boolean.
    *
    * @return The value
    */
   public boolean getBoolean() {
      if ( type == Types.BOOLEAN )
         return ((Boolean)value).booleanValue();
      else
         return "[true][yes][1][y][on]".indexOf("["+value.toString().toLowerCase()+"]") != -1;
   }

   /**
    * getByte returns the value as a byte.
    *
    * @return The value
    */
   public byte getByte() {
      if ( type == Types.BYTE )
         return ((Byte)value).byteValue();
      else
         return Byte.parseByte(value.toString());
   }

   /**
    * getChar returns the value as a char.
    *
    * @return The value
    */
   public char getChar() {
      if ( type == Types.CHAR )
         return ((Character)value).charValue();
      else
         return value.toString().charAt(0);
   }

   /**
    * getShort returns the value as a short.
    *
    * @return The value
    */
   public short getShort() {
      if ( type == Types.SHORT )
         return ((Short)value).shortValue();
      else
         return Short.parseShort(value.toString());
   }

   /**
    * getInt returns the value as an int.
    *
    * @return The value
    */
   public int getInt() {
      if ( type == Types.INT )
         return ((Integer)value).intValue();
      else
         return Integer.parseInt(value.toString());
   }

   /**
    * getLong returns the value as a long.
    *
    * @return The value
    */
   public long getLong() {
      if ( type == Types.LONG )
         return ((Long)value).longValue();
      else
         return Long.parseLong(value.toString());
   }

   /**
    * getFloat returns the value as a float.
    *
    * @return The value
    */
   public float getFloat() {
      if ( type == Types.FLOAT )
         return ((Float)value).floatValue();
      else
         return Float.parseFloat(value.toString());
   }

   /**
    * getDouble returns the value as a double.
    *
    * @return The value
    */
   public double getDouble() {
      if ( type == Types.DOUBLE )
         return ((Double)value).doubleValue();
      else
         return Double.parseDouble(value.toString());
   }

   /**
    * getElement returns the value as an Element.
    *
    * @return The value
    */
   public Element getElement() {
      if ( type == Types.ELEMENT )
         return (Element)value;
      else
         return null;
   }

   /**
    * getDocument returns the value as a Document.
    *
    * @return The value
    */
   public Document getDocument() {
      if ( type == Types.DOCUMENT )
         return (Document)value;
      else
         return null;
   }

   /**
    * getDocumentFragment returns the value as a DocumentFragment.
    *
    * @return The value
    */
   public DocumentFragment getDocumentFragment() {
      if ( type == Types.DOCUMENTFRAGMENT )
         return (DocumentFragment)value;
      else
         return null;
   }

   /**
    * getArgs returns the value as an Args instance.
    *
    * @return The value
    */
   public Args getArgs() {
      if ( type == Types.ARGS )
         return (Args)value;
      else
         return null;
   }

   /**
    * getObject returns the value as an Object.
    *
    * @return The value
    */
   public Object getObject() {
      return value;
   }

   /**
    * toString returns the value as a Stringified representation.
    *
    * @return The stringified value
    */
   public String toString() {
      switch ( type ) {

         case Types.ELEMENT:
         case Types.DOCUMENT:
         case Types.DOCUMENTFRAGMENT:
            return TextWriter.toString((Node)value);

         default:
            return value.toString();

      }
   }
}

