You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by th...@apache.org on 2003/06/26 22:58:21 UTC

cvs commit: db-ojb/src/test/org/apache/ojb/broker/metadata ObjectReferenceDescriptor.java

thma        2003/06/26 13:58:21

  Added:       src/test/org/apache/ojb/broker/metadata
                        ObjectReferenceDescriptor.java
  Log:
  ???
  
  Revision  Changes    Path
  1.1                  db-ojb/src/test/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java
  
  Index: ObjectReferenceDescriptor.java
  ===================================================================
  package org.apache.ojb.broker.metadata;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  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
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * 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 APACHE SOFTWARE FOUNDATION 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.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.Vector;
  import java.util.Collection;
  import java.lang.reflect.Modifier;
  
  import org.apache.commons.lang.builder.ToStringBuilder;
  import org.apache.ojb.broker.OJBRuntimeException;
  import org.apache.ojb.broker.PersistenceBrokerException;
  import org.apache.ojb.broker.util.logging.LoggerFactory;
  import org.apache.ojb.broker.util.logging.Logger;
  import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
  
  /**
   * Describes a Field containing a reference to another class. Provides handling for foreign keys etc.
   * <br>
   * Note: Be careful when use references of this class or caching instances of this class,
   * because instances could become invalid (see {@link MetadataManager}).
   *
   * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
   *
   */
  public class ObjectReferenceDescriptor extends AttributeDescriptorBase implements XmlCapable
  {
      private Class m_ClassOfItems = null;
      private Vector m_ForeignKeyFields = new Vector();
      private boolean m_CascadeRetrieve = true;
      private boolean m_CascadeStore = false;
      private boolean m_CascadeDelete = false;
      private Class m_ProxyOfItems = null;
      private boolean m_LookedUpProxy = false;
  
      //private Logger logger = LoggerFactory.getLogger(ObjectReferenceDescriptor.class);
  
      /**
       * holds the foreign-key field descriptor array for a specified class
       */
      private Hashtable fkFieldMap = new Hashtable();
      /**
       * define loading strategy of the resulting object
       */
      private boolean lazy = false;
      /**
       * if true relationship is refreshed when owner is found in cache
       */
      private boolean refresh = false;
  
      /**
       *
       */
      public ObjectReferenceDescriptor(ClassDescriptor descriptor)
      {
          super(descriptor);
      }
  
      /**
       *
       */
      public Class getItemProxyClass() throws PersistenceBrokerException
      {
          if (!m_LookedUpProxy)
          {
              m_ProxyOfItems = getClassDescriptor().getRepository().
                                  getDescriptorFor(m_ClassOfItems).getProxyClass();
              m_LookedUpProxy = true;
          }
          return m_ProxyOfItems;
      }
  
      /**
       * Find the first concrete Class in the specified extent.
       * @param mif
       * @return
       */
      private static ClassDescriptor findFirstConcreteClass(ClassDescriptor mif)
      {
        if (!mif.isInterface())
        {
  
          return mif;
        }
  
        Collection extentClasses = mif.getExtentClasses();
        for (Iterator iter = extentClasses.iterator(); iter.hasNext(); )
        {
          Class nextClass = (Class)iter.next();
          ClassDescriptor nextCld = mif.getRepository().getDescriptorFor(nextClass);
          ClassDescriptor firstConcreteCld = findFirstConcreteClass(nextCld);
          if (firstConcreteCld != null)
          {
            return firstConcreteCld;
          }
        }
        return null;
      }
  
      /**
       *
       */
      public FieldDescriptor[] getForeignKeyFieldDescriptors(ClassDescriptor mif)
      {
          FieldDescriptor[] foreignKeyFieldDescriptors = null;
          if ((foreignKeyFieldDescriptors = (FieldDescriptor[]) fkFieldMap.get(mif)) == null)
          {
              // 1. collect vector of indices of Fk-Fields
              Vector v = getForeignKeyFields();
              // 2. get FieldDescriptor for each index from Class-descriptor
              // 2A. In a many-to-many relationship foreignkeyfields vector will be null.
              if (v != null)
              {
                  Vector ret;
                  mif = findFirstConcreteClass(mif);
                  if (mif == null)
                  {
                    throw new OJBRuntimeException("There is no concrete class in the extent of: " + mif.getClassNameOfObject());
                  }
                  ret = new Vector();
  
                  Iterator iter = v.iterator();
                  while (iter.hasNext())
                  {
                      Object fk = iter.next();
  	            FieldDescriptor fkfd;
  		    if (fk instanceof Integer)
  		    {
  			Integer index = (Integer) fk;
  			fkfd = mif.getFieldDescriptorByIndex(index.intValue());
  		    }
  		    else
  		    {
  			fkfd = mif.getFieldDescriptorByName((String) fk);
  		    }
  		    if (fkfd == null)
  		    {
  			throw new OJBRuntimeException("Incorrect field reference \"" + fk + "\" in " + this);
  		    }
  		    ret.add(fkfd);
                  }
                  foreignKeyFieldDescriptors =
                          (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
                  fkFieldMap.put(mif, foreignKeyFieldDescriptors);
              }
          }
          return foreignKeyFieldDescriptors;
      }
  
      /**
       * @throws MetadataException if an error occours while accessing ForeingKey values on obj
       */
      public Object[] getForeignKeyValues(Object obj, ClassDescriptor mif)
              throws PersistenceBrokerException
      {
          FieldDescriptor[] fks = getForeignKeyFieldDescriptors(mif);
          Object[] result = new Object[fks.length];
          for (int i = 0; i < result.length; i++)
          {
              FieldDescriptor fmd = fks[i];
              PersistentField f = fmd.getPersistentField();
  
              // BRJ: do NOT convert.
              // conversion is done when binding the sql-statement
              //
              // FieldConversion fc = fmd.getFieldConversion();
              // Object val = fc.javaToSql(f.get(obj));
  
              Object val = f.get(obj);
              result[i] = val;
          }
          return result;
      }
  
      /**
       *
       */
      public Class getItemClass()
      {
          return m_ClassOfItems;
      }
  
      /**
       * @return the fully qualified name of the item class for this descriptor.
       */
      public String getItemClassName()
      {
          return this.m_ClassOfItems != null ? this.m_ClassOfItems.getName() : null;
      }
  
      /**
       * sets the item class
       * @param c the items class object
       */
      public void setItemClass(Class c)
      {
          m_ClassOfItems = c;
      }
  
      /**
       *
       */
      public Vector getForeignKeyFields()
      {
          return m_ForeignKeyFields;
      }
  
      /**
       *
       */
      public void setForeignKeyFields(Vector vec)
      {
          m_ForeignKeyFields = vec;
      }
  
      /**
       * add a foreign key field ID
       */
      public void addForeignKeyField(int newId)
      {
          if (m_ForeignKeyFields == null)
          {
              m_ForeignKeyFields = new Vector();
          }
          m_ForeignKeyFields.add(new Integer(newId));
      }
  
      /**
       * add a foreign key field
       */
      public void addForeignKeyField(String newField)
      {
          if (m_ForeignKeyFields == null)
          {
              m_ForeignKeyFields = new Vector();
          }
          m_ForeignKeyFields.add(newField);
      }
  
      /**
       * Gets the refresh.
       * @return Returns a boolean
       */
      public boolean isRefresh()
      {
          return refresh;
      }
  
      /**
       * Sets the refresh.
       * @param refresh The refresh to set
       */
      public void setRefresh(boolean refresh)
      {
          this.refresh = refresh;
      }
  
      /**
       * Gets the lazy.
       * @return Returns a boolean
       */
      public boolean isLazy()
      {
          return lazy;
      }
  
      /**
       * Sets the lazy.
       * @param lazy The lazy to set
       */
      public void setLazy(boolean lazy)
      {
          this.lazy = lazy;
      }
  
      /**
       *
       */
      public boolean getCascadeRetrieve()
      {
          return m_CascadeRetrieve;
      }
  
      /**
       *
       */
      public void setCascadeRetrieve(boolean b)
      {
          m_CascadeRetrieve = b;
      }
  
      /**
       *
       */
      public boolean getCascadeStore()
      {
          return m_CascadeStore;
      }
  
      /**
       *
       */
      public void setCascadeStore(boolean b)
      {
          m_CascadeStore = b;
      }
  
      /**
       *
       */
      public boolean getCascadeDelete()
      {
          return m_CascadeDelete;
      }
  
      /**
       *
       */
      public void setCascadeDelete(boolean b)
      {
          m_CascadeDelete = b;
      }
  
      public String toString()
      {
          return new ToStringBuilder(this)
                  .append("cascade delete", m_CascadeDelete)
                  .append("cascade retrieve", m_CascadeRetrieve)
                  .append("cascade store", m_CascadeStore)
                  .append("is lazy", lazy)
                  .append("class of Items", m_ClassOfItems)
                  .toString();
      }
  
      /*
       * @see XmlCapable#toXML()
       */
      public String toXML()
      {
          RepositoryTags tags = RepositoryTags.getInstance();
          String eol = System.getProperty("line.separator");
  
          // opening tag
          String result = "      " + tags.getOpeningTagNonClosingById(REFERENCE_DESCRIPTOR) + eol;
  
          // attributes
          // name
          String name = this.getAttributeName();
          if (name == null)
          {
          	name = tags.TAG_SUPER;
          }
          result += "        " + tags.getAttribute(FIELD_NAME, name) + eol;
  
          // class-ref
          result += "        " + tags.getAttribute(REFERENCED_CLASS, this.getItemClassName()) + eol;
  
          // proxyReference is optional
          if (isLazy())
          {
              result += "        " + tags.getAttribute(PROXY_REFERENCE, "true") + eol;
          }
  
          //reference refresh is optional, disabled by default
          if (isRefresh())
          {
              result += "        " + tags.getAttribute(REFRESH, "true") + eol;
          }
  
          //auto retrieve is optional, enabled by default
          if (!getCascadeRetrieve())
          {
              result += "        " + tags.getAttribute(AUTO_RETRIEVE, "false") + eol;
          }
  
          //auto update is optional, disabled by default
          if (getCascadeStore())
          {
              result += "        " + tags.getAttribute(AUTO_UPDATE, "true") + eol;
          }
  
          //auto delete is optional, disabled by default
          if (getCascadeDelete())
          {
              result += "        " + tags.getAttribute(AUTO_DELETE, "true") + eol;
          }
  
          // close opening tag
          result += "      >" + eol;
  
          // elements
          // write foreignkey elements
          for (int i = 0; i < getForeignKeyFields().size(); i++)
          {
              Object obj = getForeignKeyFields().get(i);
  	    if (obj instanceof Integer)
  	    {
          	String fkId = obj.toString();
                  result += "        " + tags.getOpeningTagNonClosingById(FOREIGN_KEY) + " ";
  	        result += tags.getAttribute(FIELD_ID_REF, fkId) + "/>" + eol;
  	    }
  	    else
  	    {
          	String fk = (String) obj;
                  result += "        " + tags.getOpeningTagNonClosingById(FOREIGN_KEY) + " ";
  	        result += tags.getAttribute(FIELD_REF, fk) + "/>" + eol;
  	    }
          }
  
          // closing tag
          result += "      " + tags.getClosingTagById(REFERENCE_DESCRIPTOR) + eol;
          return result;
      }
  }