/*
 * Generated by XDoclet - Do not edit!
 */
package test.interfaces;

/**
 * Value object for Customer.
 *
 * Notice, this object is used to represent the state of an 
 * Customer object. This value object
 * Is not connected to the database in any way, it is just a normal object used 
 * as a container for data from an EJB. 
 *
 * @xdoclet-generated at 16-04-05
 * @copyright The XDoclet Team
 * @author XDoclet
 * @version 1.2.3
 */
public class CustomerNormalValue
   extends java.lang.Object
   implements java.io.Serializable, java.lang.Cloneable 
{

   private float credit;
   private boolean creditHasBeenSet = false;

   private java.lang.String[][] array;
   private boolean arrayHasBeenSet = false;

   private byte[] image;
   private boolean imageHasBeenSet = false;

   private float tax;
   private boolean taxHasBeenSet = false;

   private java.lang.String id;
   private boolean idHasBeenSet = false;

   private java.lang.String name;
   private boolean nameHasBeenSet = false;

   private java.lang.String firstName;
   private boolean firstNameHasBeenSet = false;
   private java.util.Collection AccountViews = wrapCollection(new java.util.ArrayList() );

   private java.util.Collection ShippingAddressValues = wrapCollection(new java.util.ArrayList() );

   private test.interfaces.CustomerPK primaryKey;

   private int _version = 0;

   public CustomerNormalValue()
   {
	  primaryKey = new test.interfaces.CustomerPK();
   }

   public CustomerNormalValue( float credit,java.lang.String[][] array,byte[] image,float tax,java.lang.String id,java.lang.String name,java.lang.String firstName )
   {
       setCredit(credit);
       setArray(array);
       setImage(image);
       setTax(tax);
       setId(id);
       setName(name);
       setFirstName(firstName);
       primaryKey = new test.interfaces.CustomerPK(this.getId());
   }

   /**
    * @deprecated use {@link #clone}
    */
   public CustomerNormalValue( CustomerNormalValue otherValue )
   {
	  this.credit = otherValue.credit;
	  creditHasBeenSet = true;
	  this.array = otherValue.array;
	  arrayHasBeenSet = true;
	  this.image = otherValue.image;
	  imageHasBeenSet = true;
	  this.tax = otherValue.tax;
	  taxHasBeenSet = true;
	  this.id = otherValue.id;
	  idHasBeenSet = true;
	  this.name = otherValue.name;
	  nameHasBeenSet = true;
	  this.firstName = otherValue.firstName;
	  firstNameHasBeenSet = true;
	  this.AccountViews.addAll(otherValue.AccountViews);
	  this.ShippingAddressValues.addAll(otherValue.ShippingAddressValues);

	  primaryKey = new test.interfaces.CustomerPK(this.getId());
   }

   public test.interfaces.CustomerPK getPrimaryKey()
   {
	  return primaryKey;
   }

   public void setPrimaryKey( test.interfaces.CustomerPK primaryKey)
   {
      // it's also nice to update PK object - just in case
      // somebody would ask for it later...
      this.primaryKey = primaryKey;
	  setId( primaryKey.id );
   }

   public float getCredit()
   {
	  return this.credit;
   }

   public void setCredit( float credit )
   {
	  this.credit = credit;
	  creditHasBeenSet = true;

   }

   public boolean creditHasBeenSet(){
	  return creditHasBeenSet;
   }
   public java.lang.String[][] getArray()
   {
	  return this.array;
   }

   private void setArray( java.lang.String[][] array )
   {
	  this.array = array;
	  arrayHasBeenSet = true;

   }

   public byte[] getImage()
   {
	  return this.image;
   }

   private void setImage( byte[] image )
   {
	  this.image = image;
	  imageHasBeenSet = true;

   }

   public float getTax()
   {
	  return this.tax;
   }

   private void setTax( float tax )
   {
	  this.tax = tax;
	  taxHasBeenSet = true;

   }

   public java.lang.String getId()
   {
	  return this.id;
   }

   public void setId( java.lang.String id )
   {
	  this.id = id;
	  idHasBeenSet = true;

      primaryKey.setId(id);
   }

   public boolean idHasBeenSet(){
	  return idHasBeenSet;
   }
   public java.lang.String getName()
   {
	  return this.name;
   }

   public void setName( java.lang.String name )
   {
	  this.name = name;
	  nameHasBeenSet = true;

   }

   public boolean nameHasBeenSet(){
	  return nameHasBeenSet;
   }
   public java.lang.String getFirstName()
   {
	  return this.firstName;
   }

   public void setFirstName( java.lang.String firstName )
   {
	  this.firstName = firstName;
	  firstNameHasBeenSet = true;

   }

   public boolean firstNameHasBeenSet(){
	  return firstNameHasBeenSet;
   }

   protected java.util.Collection addedAccountViews = wrapCollection(new java.util.ArrayList());
   protected java.util.Collection onceAddedAccountViews = wrapCollection(new java.util.ArrayList());
   protected java.util.Collection removedAccountViews = wrapCollection(new java.util.ArrayList());
   protected java.util.Collection updatedAccountViews = wrapCollection(new java.util.ArrayList());

   /**
    * Important: This method returns an unmodifiable collection.
    */
   public java.util.Collection getAddedAccountViews() { return wrapReadOnly(addedAccountViews); }

   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getOnceAddedAccountViews() { return wrapReadOnly(onceAddedAccountViews); }
   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getRemovedAccountViews() { return wrapReadOnly(removedAccountViews); }
   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getUpdatedAccountViews() { return wrapReadOnly(updatedAccountViews); }
   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getAccountViewCollection() { return wrapReadOnly(AccountViews); }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    * 
    * @deprecated
    */
   public void setAddedAccountViews(java.util.Collection addedAccountViews)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(addedAccountViews.toArray());
      this.addedAccountViews.clear();
      this.addedAccountViews.addAll(tempList);
   }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    * 
    * @deprecated
    */
   public void setOnceAddedAccountViews(java.util.Collection onceAddedAccountViews)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(onceAddedAccountViews.toArray());
      this.onceAddedAccountViews.clear();
      this.onceAddedAccountViews.addAll(tempList);
    }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    * 
    * @deprecated
    */
   public void setRemovedAccountViews(java.util.Collection removedAccountViews)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(removedAccountViews.toArray());
      this.removedAccountViews.clear();
      this.removedAccountViews.addAll(tempList);
   }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    *  
    * @deprecated
    */
   public void setUpdatedAccountViews(java.util.Collection updatedAccountViews)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(updatedAccountViews.toArray());
      this.updatedAccountViews.clear();
      this.updatedAccountViews.addAll(tempList);
   }

   /**
    * This method fetches the contents of the underlying collection as an Array.
    * It is a relatively expensive operation, so use the collections if you can.
    * 
    * This operation is atomic and threadsafe unless the synchronization type is "none".
    * 
    * This operation is deprecated, as it is fairly expensive and should be discouraged.
    * 
    * @deprecated
    */
   public test.interfaces.AccountValue[] getAccountViews()
   {
	return (test.interfaces.AccountValue[])this.AccountViews.toArray(new test.interfaces.AccountValue[AccountViews.size()]);
   }

   /**
    * This method sets the contents of the given attribute to the contents of the
    * given array.
    * 
    * This operation is atomic and threadsafe unless the synchronization type is "none".
    * 
    * This operation is deprecated, as it is fairly expensive and should be discouraged.
    * 
    * @deprecated
    */
   public void setAccountViews(test.interfaces.AccountValue[] AccountViews)
   {
      this.AccountViews.clear();
      for (int i=0; i < AccountViews.length; i++) {
        this.AccountViews.add(AccountViews[i]);
      }
   }

   public void clearAccountViews()
   {
	  this.AccountViews.clear();
   }

   /**
    * When we're adding an aggregate object, we check if it was previously removed, and
    * if it was, we check if it was ever added. If the user adds an object, then removes
    * it then adds it again, we keep the object in the added collection. If the user
    * just removes an object (thas wasn't added in this session, just existed before) then
    * adds it again, we assume the user is updating a current existing object, so it will
    * end in the updated collection.
    */
   public void addAccountView(test.interfaces.AccountValue added)
   {
	  this.AccountViews.add(added);

      if (this.removedAccountViews.contains(added))
      {
        this.removedAccountViews.remove(added);
        if (this.onceAddedAccountViews.contains(added))
        {
          if (! this.addedAccountViews.contains(added))
            this.addedAccountViews.add(added);
        }
        else if (! this.updatedAccountViews.contains(added))
        {
            this.updatedAccountViews.add(added);
        }
      }
      else
      {
        if (! this.onceAddedAccountViews.contains(added))
          this.onceAddedAccountViews.add(added);
        if (! this.addedAccountViews.contains(added))
          this.addedAccountViews.add(added);
      }
   }

   /**
    * If we're removing an object that was previously added, we just remove it from
    * the added collection and don't add it in the remove collection. The user has
    * just given up on creating the object. If we're removing a previously updated
    * object, we remove it from the updated collection, since it will be removed
    * anyway.
    */
   public void removeAccountView(test.interfaces.AccountValue removed)
   {
      this.AccountViews.remove(removed);

      if (this.addedAccountViews.contains(removed))
        this.addedAccountViews.remove(removed);
      else if (! this.removedAccountViews.contains(removed))
        this.removedAccountViews.add(removed);

      if (this.updatedAccountViews.contains(removed))
        this.updatedAccountViews.remove(removed);
   }

   public void updateAccountView(test.interfaces.AccountValue updated)
   {
      if ( !this.updatedAccountViews.contains(updated) && !this.addedAccountViews.contains(updated))
             this.updatedAccountViews.add(updated);

      if (this.removedAccountViews.contains(updated))
         this.removedAccountViews.remove(updated);
   }

   public void cleanAccountView(){
	this.addedAccountViews.clear();
        this.onceAddedAccountViews.clear();
	this.removedAccountViews.clear();
	this.updatedAccountViews.clear();
   }

   public void copyAccountViewsFrom(test.interfaces.CustomerNormalValue from)
   {
        this.AccountViews.clear();
        this.AccountViews.addAll(from.AccountViews);
   }
   protected java.util.Collection addedShippingAddressValues = wrapCollection(new java.util.ArrayList());
   protected java.util.Collection onceAddedShippingAddressValues = wrapCollection(new java.util.ArrayList());
   protected java.util.Collection removedShippingAddressValues = wrapCollection(new java.util.ArrayList());
   protected java.util.Collection updatedShippingAddressValues = wrapCollection(new java.util.ArrayList());

   /**
    * Important: This method returns an unmodifiable collection.
    */
   public java.util.Collection getAddedShippingAddressValues() { return wrapReadOnly(addedShippingAddressValues); }

   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getOnceAddedShippingAddressValues() { return wrapReadOnly(onceAddedShippingAddressValues); }
   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getRemovedShippingAddressValues() { return wrapReadOnly(removedShippingAddressValues); }
   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getUpdatedShippingAddressValues() { return wrapReadOnly(updatedShippingAddressValues); }
   /**
    * Important: This method returns an unmodifiable collection.
    */
    public java.util.Collection getShippingAddressValueCollection() { return wrapReadOnly(ShippingAddressValues); }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    * 
    * @deprecated
    */
   public void setAddedShippingAddressValues(java.util.Collection addedShippingAddressValues)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(addedShippingAddressValues.toArray());
      this.addedShippingAddressValues.clear();
      this.addedShippingAddressValues.addAll(tempList);
   }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    * 
    * @deprecated
    */
   public void setOnceAddedShippingAddressValues(java.util.Collection onceAddedShippingAddressValues)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(onceAddedShippingAddressValues.toArray());
      this.onceAddedShippingAddressValues.clear();
      this.onceAddedShippingAddressValues.addAll(tempList);
    }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    * 
    * @deprecated
    */
   public void setRemovedShippingAddressValues(java.util.Collection removedShippingAddressValues)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(removedShippingAddressValues.toArray());
      this.removedShippingAddressValues.clear();
      this.removedShippingAddressValues.addAll(tempList);
   }

   /**
    * This will set the contents of the underlying collection to the contents of the
    * given collection. This means that any unmodifiable collections given out will
    * also change. The collections are guaranteed to be consistent, but not correct.
    * In this case, it is possible to see a collection in the process of changing,
    * it might appear to be empty for an instant, but it will behave correctly. 
    * Also, the update will be atomic with respect to the input collection
    * if the input collection is a synchronized collection.
    * 
    * This method has been deprecated, as it strains the imagination to conceive of
    * a reason for outsiders to modify these collections, which are really for our
    * own internal bookkeeping. 
    *  
    * @deprecated
    */
   public void setUpdatedShippingAddressValues(java.util.Collection updatedShippingAddressValues)
   {
      //This operation is atomic if the input collection is synchronized.
      java.util.List tempList = java.util.Arrays.asList(updatedShippingAddressValues.toArray());
      this.updatedShippingAddressValues.clear();
      this.updatedShippingAddressValues.addAll(tempList);
   }

   /**
    * This method fetches the contents of the underlying collection as an Array.
    * It is a relatively expensive operation, so use the collections if you can.
    * 
    * This operation is atomic and threadsafe unless the synchronization type is "none".
    * 
    * This operation is deprecated, as it is fairly expensive and should be discouraged.
    * 
    * @deprecated
    */
   public test.interfaces.AddressValue[] getShippingAddressValues()
   {
	return (test.interfaces.AddressValue[])this.ShippingAddressValues.toArray(new test.interfaces.AddressValue[ShippingAddressValues.size()]);
   }

   /**
    * This method sets the contents of the given attribute to the contents of the
    * given array.
    * 
    * This operation is atomic and threadsafe unless the synchronization type is "none".
    * 
    * This operation is deprecated, as it is fairly expensive and should be discouraged.
    * 
    * @deprecated
    */
   public void setShippingAddressValues(test.interfaces.AddressValue[] ShippingAddressValues)
   {
      this.ShippingAddressValues.clear();
      for (int i=0; i < ShippingAddressValues.length; i++) {
        this.ShippingAddressValues.add(ShippingAddressValues[i]);
      }
   }

   public void clearShippingAddressValues()
   {
	  this.ShippingAddressValues.clear();
   }

   /**
    * When we're adding an aggregate object, we check if it was previously removed, and
    * if it was, we check if it was ever added. If the user adds an object, then removes
    * it then adds it again, we keep the object in the added collection. If the user
    * just removes an object (thas wasn't added in this session, just existed before) then
    * adds it again, we assume the user is updating a current existing object, so it will
    * end in the updated collection.
    */
   public void addShippingAddressValue(test.interfaces.AddressValue added)
   {
	  this.ShippingAddressValues.add(added);

      if (this.removedShippingAddressValues.contains(added))
      {
        this.removedShippingAddressValues.remove(added);
        if (this.onceAddedShippingAddressValues.contains(added))
        {
          if (! this.addedShippingAddressValues.contains(added))
            this.addedShippingAddressValues.add(added);
        }
        else if (! this.updatedShippingAddressValues.contains(added))
        {
            this.updatedShippingAddressValues.add(added);
        }
      }
      else
      {
        if (! this.onceAddedShippingAddressValues.contains(added))
          this.onceAddedShippingAddressValues.add(added);
        if (! this.addedShippingAddressValues.contains(added))
          this.addedShippingAddressValues.add(added);
      }
   }

   /**
    * If we're removing an object that was previously added, we just remove it from
    * the added collection and don't add it in the remove collection. The user has
    * just given up on creating the object. If we're removing a previously updated
    * object, we remove it from the updated collection, since it will be removed
    * anyway.
    */
   public void removeShippingAddressValue(test.interfaces.AddressValue removed)
   {
      this.ShippingAddressValues.remove(removed);

      if (this.addedShippingAddressValues.contains(removed))
        this.addedShippingAddressValues.remove(removed);
      else if (! this.removedShippingAddressValues.contains(removed))
        this.removedShippingAddressValues.add(removed);

      if (this.updatedShippingAddressValues.contains(removed))
        this.updatedShippingAddressValues.remove(removed);
   }

   public void updateShippingAddressValue(test.interfaces.AddressValue updated)
   {
      if ( !this.updatedShippingAddressValues.contains(updated) && !this.addedShippingAddressValues.contains(updated))
             this.updatedShippingAddressValues.add(updated);

      if (this.removedShippingAddressValues.contains(updated))
         this.removedShippingAddressValues.remove(updated);
   }

   public void cleanShippingAddressValue(){
	this.addedShippingAddressValues.clear();
        this.onceAddedShippingAddressValues.clear();
	this.removedShippingAddressValues.clear();
	this.updatedShippingAddressValues.clear();
   }

   public void copyShippingAddressValuesFrom(test.interfaces.CustomerNormalValue from)
   {
        this.ShippingAddressValues.clear();
        this.ShippingAddressValues.addAll(from.ShippingAddressValues);
   }

   public int getVersion()
   {
	  return _version;
   }
   public void setVersion(int version)
   {
	  this._version = version;
   }

   public String toString()
   {
	  StringBuffer str = new StringBuffer("{");

	  str.append("credit=" + getCredit() + " " + "array=" + getArray() + " " + "image=" + getImage() + " " + "tax=" + getTax() + " " + "id=" + getId() + " " + "name=" + getName() + " " + "firstName=" + getFirstName());
	  str.append(",version=");
	  str.append(_version);
	  str.append('}');

	  return(str.toString());
   }

   /**
    * A Value Object has an identity if the attributes making its Primary Key have all been set. An object without identity is never equal to any other object.
    *
    * @return true if this instance has an identity.
    */
   protected boolean hasIdentity()
   {
	  boolean ret = true;
	  ret = ret && idHasBeenSet;
	  return ret;
   }

   /**
    *
    * @deprecated use {@link #equals}
    */
   public boolean isIdentical(Object other)
   {
          if (other instanceof CustomerNormalValue)
          {
                 CustomerNormalValue that = (CustomerNormalValue) other;
                 boolean lEquals = true;
                 lEquals = lEquals && this.credit == that.credit;
                 if( this.array == null )
                 {
                        lEquals = lEquals && ( that.array == null );
                 }
                 else
                 {
                        lEquals = lEquals && this.array.equals( that.array );
                 }
                 lEquals = lEquals && this.image == that.image;
                 lEquals = lEquals && this.tax == that.tax;
                 if( this.name == null )
                 {
                        lEquals = lEquals && ( that.name == null );
                 }
                 else
                 {
                        lEquals = lEquals && this.name.equals( that.name );
                 }
                 if( this.firstName == null )
                 {
                        lEquals = lEquals && ( that.firstName == null );
                 }
                 else
                 {
                        lEquals = lEquals && this.firstName.equals( that.firstName );
                 }
                 if( this.getAccountViews() == null )
                 {
                        lEquals = lEquals && ( that.getAccountViews() == null );
                 }
                 else
                 {
                        lEquals = lEquals && java.util.Arrays.equals(this.getAccountViews() , that.getAccountViews()) ;
                 }
                 if( this.getShippingAddressValues() == null )
                 {
                        lEquals = lEquals && ( that.getShippingAddressValues() == null );
                 }
                 else
                 {
                        lEquals = lEquals && java.util.Arrays.equals(this.getShippingAddressValues() , that.getShippingAddressValues()) ;
                 }

                 return lEquals;
          }
          else
          {
                 return false;
          }
   }

    public boolean equals(Object other) {

        //If it's not the correct type, clearly it isn't equal to this.
        if (!(other instanceof CustomerNormalValue)) { 
            return false;
        }

        return equals((CustomerNormalValue) other);
    }

    /**
     * This class is not using strict ordering. This means that the object is not Comparable, and
     * each check for equality will test all members for equality. We do not check collections for
     * equality however, so you would be wise to not use this if you have collection typed EJB References.
     */
    public boolean equals(CustomerNormalValue that) {

        //try to get lucky.
        if (this == that) {
            return true;
        }
        //this clearly isn't null.
        if(null == that) {
            return false;
        }

        if(this.credit != that.credit) {
            return false;
        }

        if(this.array != that.array) {

            if( this.array == null || that.array == null ) {
                return false;
            }

            if(!this.array.equals(that.array)) {
                return false;
            }

        }

        if(!java.util.Arrays.equals(this.image, that.image)) {
            return false;
        }

        if(this.tax != that.tax) {
            return false;
        }

        if(this.id != that.id) {

            if( this.id == null || that.id == null ) {
                return false;
            }

            if(!this.id.equals(that.id)) {
                return false;
            }

        }

        if(this.name != that.name) {

            if( this.name == null || that.name == null ) {
                return false;
            }

            if(!this.name.equals(that.name)) {
                return false;
            }

        }

        if(this.firstName != that.firstName) {

            if( this.firstName == null || that.firstName == null ) {
                return false;
            }

            if(!this.firstName.equals(that.firstName)) {
                return false;
            }

        }

	     // AccountView is an aggregate type. We won't compare the contents of collections (for performance reasons), so note
         //that these will not be considered when calculating equality or hash codes. You would be wise to use strict ordering if possible, as that makes
         //for more tractable behavior.
	     // ShippingAddressValue is an aggregate type. We won't compare the contents of collections (for performance reasons), so note
         //that these will not be considered when calculating equality or hash codes. You would be wise to use strict ordering if possible, as that makes
         //for more tractable behavior.

        return true;

    }

    public Object clone() throws java.lang.CloneNotSupportedException {
        CustomerNormalValue other = (CustomerNormalValue) super.clone();

        {
        //Anonymous block to protect from namespace collisions.
        java.util.Collection tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.AccountViews);
        this.AccountViews = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.addedAccountViews);
        this.addedAccountViews = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.onceAddedAccountViews);
        this.onceAddedAccountViews = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.removedAccountViews);
        this.removedAccountViews = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.updatedAccountViews);
        this.updatedAccountViews = tempData;
        }
        {
        //Anonymous block to protect from namespace collisions.
        java.util.Collection tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.ShippingAddressValues);
        this.ShippingAddressValues = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.addedShippingAddressValues);
        this.addedShippingAddressValues = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.onceAddedShippingAddressValues);
        this.onceAddedShippingAddressValues = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.removedShippingAddressValues);
        this.removedShippingAddressValues = tempData;
        tempData = wrapCollection(new java.util.ArrayList());
        tempData.addAll(this.updatedShippingAddressValues);
        this.updatedShippingAddressValues = tempData;
        }

        return other;
    }

    public ReadOnlyCustomerNormalValue getReadOnlyCustomerNormalValue() {
        return new ReadOnlyCustomerNormalValue();
    }

    public int hashCode(){
	  int result = 17;
      result = 37*result + Float.floatToIntBits(credit);

      result = 37*result + ((this.array != null) ? this.array.hashCode() : 0);

      if (image != null) {
        for (int i=0; i<image.length; i++)
        {
          long l = image[i];
          result = 37*result + (int)(l^(l>>>32));
        }
      }

      result = 37*result + Float.floatToIntBits(tax);

      result = 37*result + ((this.id != null) ? this.id.hashCode() : 0);

      result = 37*result + ((this.name != null) ? this.name.hashCode() : 0);

      result = 37*result + ((this.firstName != null) ? this.firstName.hashCode() : 0);

      // AccountView is an aggregate type. We won't compare the contents of collections (for performance reasons), so note
      //that these will not be considered when calculating equality or hash codes. You would be wise to use strict ordering if possible, as that makes
      //for more tractable behavior.
      // ShippingAddressValue is an aggregate type. We won't compare the contents of collections (for performance reasons), so note
      //that these will not be considered when calculating equality or hash codes. You would be wise to use strict ordering if possible, as that makes
      //for more tractable behavior.

	  return result;
    }

    /**
     * Covariant function so the compiler can choose the proper one at compile time,
     * eliminates the need for XDoclet to really understand compiletime typing.
     *
     * Read only collections need to be synchronized. Once we start giving out handles
     * to these collections, they'll be used in other threads sooner or later. 
     */
    private static java.util.Collection wrapCollection(java.util.Collection input) {
        return java.util.Collections.synchronizedCollection(input);
    }
    /**
     * Covariant function so the compiler can choose the proper one at compile time,
     * eliminates the need for XDoclet to really understand compiletime typing.
     *
     * Read only collections need to be synchronized. Once we start giving out handles
     * to these collections, they'll be used in other threads sooner or later. 
     */
    private static java.util.Set wrapCollection(java.util.Set input) {
        return java.util.Collections.synchronizedSet(input);
    }
    /**
     * Covariant function. This is used in covariant form so that the compiler
     * can do some of our conditional branches for us. If I made these functions
     * have different names, then XDoclet would have to choose between them based on 
     * compiletime types, that wouldn't be easy. 
     */
    private static java.util.Collection wrapReadOnly(java.util.Collection input) {
        return java.util.Collections.unmodifiableCollection(input);
    }
    /**
     * Covariant function. This is used in covariant form so that the compiler
     * can do some of our conditional branches for us. If I made these functions
     * have different names, then XDoclet would have to choose between them based on 
     * compiletime types, that wouldn't be easy. 
     */
    private static java.util.Set wrapReadOnly(java.util.Set input) {
        return java.util.Collections.unmodifiableSet(input);
    }

    private final class ReadOnlyCustomerNormalValue 
    implements java.lang.Cloneable, java.io.Serializable 
    {
        private CustomerNormalValue underlying() {
            return CustomerNormalValue.this;
        }

       public float getCredit() {
              return underlying().credit;
       }

       public java.lang.String[][] getArray() {
              return underlying().array;
       }

       public byte[] getImage() {
              return underlying().image;
       }

       public float getTax() {
              return underlying().tax;
       }

       public java.lang.String getId() {
              return underlying().id;
       }

       public java.lang.String getName() {
              return underlying().name;
       }

       public java.lang.String getFirstName() {
              return underlying().firstName;
       }

       public java.util.Collection getAddedAccountViews() {
            return underlying().getAddedAccountViews(); 
       }
       public java.util.Collection getOnceAddedAccountViews() {
            return underlying().getOnceAddedAccountViews(); 
       }
       public java.util.Collection getRemovedAccountViews() {
            return underlying().getRemovedAccountViews(); 
       }
       public java.util.Collection getUpdatedAccountViews() {
            return underlying().getUpdatedAccountViews(); 
       }
       public java.util.Collection getAccountViewCollection()  {
            return underlying().getAccountViewCollection(); 
       }
       public java.util.Collection getAddedShippingAddressValues() {
            return underlying().getAddedShippingAddressValues(); 
       }
       public java.util.Collection getOnceAddedShippingAddressValues() {
            return underlying().getOnceAddedShippingAddressValues(); 
       }
       public java.util.Collection getRemovedShippingAddressValues() {
            return underlying().getRemovedShippingAddressValues(); 
       }
       public java.util.Collection getUpdatedShippingAddressValues() {
            return underlying().getUpdatedShippingAddressValues(); 
       }
       public java.util.Collection getShippingAddressValueCollection()  {
            return underlying().getShippingAddressValueCollection(); 
       }

        public int hashCode() {
            return 101 * underlying().hashCode();
        }

        public boolean equals(Object o) {
            if(o instanceof ReadOnlyCustomerNormalValue) {
                return this.equals((ReadOnlyCustomerNormalValue) o);
            }
            return false;
        }

        public boolean equals(ReadOnlyCustomerNormalValue that) {
            if(null == that) {
                return false;
            }

            return this.underlying().equals(that.underlying());
        }

    }

}
