Save This Page
Home » jdo2-model-2.3-ea-src » org.apache.jdo.impl.model.jdo » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software 
   12    * distributed under the License is distributed on an "AS IS" BASIS, 
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
   14    * See the License for the specific language governing permissions and 
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.jdo.impl.model.jdo;
   19   
   20   import org.apache.jdo.model.ModelException;
   21   import org.apache.jdo.model.java.JavaType;
   22   import org.apache.jdo.model.jdo.JDOClass;
   23   import org.apache.jdo.model.jdo.JDOField;
   24   import org.apache.jdo.model.jdo.JDORelationship;
   25   
   26   /**
   27    * JDORelationship is the super interface for all interfaces representing 
   28    * JDO relationship metadata of a managed field of a persistence capable class.
   29    * 
   30    * @author Michael Bouschen
   31    * @version 2.0
   32    */
   33   public abstract class JDORelationshipImpl extends JDOElementImpl
   34       implements JDORelationship {
   35       
   36       /** Property lowerBound. No default. */
   37       private int lowerBound;
   38   
   39       /** Property upperBound. No default. */
   40       private int upperBound;
   41   
   42       /** Relationship JDOField<->JDORelationship. */
   43       private JDOField declaringField;
   44   
   45       /** Relationship JDORelationship<->JDORelationship. */
   46       protected JDORelationship mappedBy;
   47   
   48       /** Name of the field which is the inverse relationship */
   49       private String inverseName;
   50   
   51       /** Relationship JDORelationship<->JDORelationship. */
   52       protected JDORelationship inverse;
   53   
   54       /** 
   55        * Get the lower cardinality bound for this relationship element.
   56        * @return the lower cardinality bound
   57        */
   58       public int getLowerBound() {
   59           return lowerBound;
   60       }
   61   
   62       /** 
   63        * Set the lower cardinality bound for this relationship element.
   64        * @param lowerBound an integer indicating the lower cardinality bound
   65        */
   66       public void setLowerBound(int lowerBound) {
   67           this.lowerBound = lowerBound;
   68       }
   69       
   70       /** 
   71        * Get the upper cardinality bound for this relationship element.
   72        * @return the upper cardinality bound
   73        */
   74       public int getUpperBound() {
   75           return upperBound;
   76       }
   77   
   78       /** 
   79        * Set the upper cardinality bound for this relationship element.
   80        * @param upperBound an integer indicating the upper cardinality bound
   81        */
   82       public void setUpperBound(int upperBound)
   83       {
   84           this.upperBound = upperBound;
   85       }
   86   
   87       /** 
   88        * Get the declaring field of this JDORelationship.
   89        * @return the field that owns this JDORelationship, or <code>null</code>
   90        * if the element is not attached to any field
   91        */
   92       public JDOField getDeclaringField() {
   93           return declaringField;
   94       }
   95   
   96       /** 
   97        * Set the declaring field of this JDORelationship.
   98        * @param declaringField the declaring field of this relationship element
   99        */
  100       public void setDeclaringField(JDOField declaringField) {
  101           this.declaringField = declaringField;
  102       }
  103   
  104       /**
  105        * Get the JDOClass corresponding to the type or element of this 
  106        * relationship.
  107        * @return the related class
  108        */
  109       public JDOClass getRelatedJDOClass() {
  110           JavaType relatedType = getRelatedJavaType();
  111   
  112           if (relatedType != null) {
  113               JDOClass myClass = getDeclaringField().getDeclaringClass();
  114               String relatedTypeName = relatedType.getName();
  115   
  116               if (relatedTypeName.equals(myClass.getName()))
  117                   return myClass;
  118           
  119               return myClass.getDeclaringModel().getJDOClass(relatedTypeName);
  120           }
  121   
  122           return null;
  123       }
  124   
  125       /** 
  126        * Get the mappedBy relationship. If there is no mappedBy relationship
  127        * set, the method checks the mappedBy name as specified in the declaring
  128        * field and resolves the relationship. The method return
  129        * <code>null</code> if there is no mappedBy relationship set and there
  130        * is no mappedBy name specified on the declaring field.
  131        * @return the mappedBy relationship if available; <code>null</code>
  132        * otherwise.
  133        */
  134       public JDORelationship getMappedBy() {
  135           if (mappedBy != null) {
  136               // return mappedBy relationship, if explicitly set by the setter
  137               return mappedBy;
  138           }
  139           
  140           // not set => check mappedByName of declaring field
  141           JDOField field = getDeclaringField();
  142           String mappedByName = field.getMappedByName();
  143           if (mappedByName != null) {
  144               // return a JDORelationship instance for the mappedBy field name
  145               // as stored in the declaring field
  146               return getInverseRelationship();
  147           }
  148           
  149           return null;
  150       }
  151   
  152       /**
  153        * Set the mappedBy relationship for this relationship. This method
  154        * automatically updates the mappedBy name of the declaring field of this
  155        * relationship.
  156        * @param mappedBy the mappedBy relationship.
  157        * @exception ModelException if impossible
  158        */
  159       public void setMappedBy(JDORelationship mappedBy) throws ModelException {
  160           this.mappedBy = mappedBy;
  161           String mappedByName = null;
  162           if (mappedBy != null) {
  163               JDOField declaringField = mappedBy.getDeclaringField();
  164               if (declaringField != null) {
  165                   mappedByName = declaringField.getName();
  166               }
  167           }
  168           getDeclaringField().setMappedByName(mappedByName);
  169           setInverseRelationship(mappedBy);
  170       }
  171   
  172       /** 
  173        * Get the relative name of the inverse relationship field for this
  174        * relationship.  In the case of two-way relationships, the two
  175        * relationships involved are inverses of each other.  If this
  176        * relationship element does not participate in a two-way relationship,
  177        * this returns <code>null</code>.  Note that it is possible to have
  178        * this method return a value, but because of the combination of
  179        * related class and lookup, there may be no corresponding
  180        * JDORelationship which can be found.
  181        * @return the relative name of the inverse JDORelationship
  182        * @see #getInverseRelationship
  183        */
  184       public String getInverseRelationshipName() {
  185           if (inverseName != null) {
  186               // return inverseName, if explicitly set
  187               return inverseName;
  188           }
  189           
  190           JDOField declaringField = getDeclaringField();
  191           String mappedByName = declaringField.getMappedByName();
  192           if (mappedByName != null) {
  193               // return mappedByName, if explicitly set on the declaring field
  194               return mappedByName;
  195           }
  196   
  197           // try to resolve relationship info from mappedByName of the field on
  198           // the other side
  199           UnresolvedRelationshipHelper info = getUnresolvedRelationshipHelper();
  200           // look for an unresolved relationship entry where the name of this
  201           // field is used as the mappedByName
  202           JDOField inverseField = 
  203               info.resolve(declaringField.getName(), getRelatedJDOClass());
  204           if (inverseField != null) {
  205               // found inverse => update inverseName and return it
  206               inverseName = inverseField.getName();
  207               return inverseName;
  208           }
  209   
  210           // no inverse name available => return null
  211           return null;
  212       }
  213   
  214       /**
  215        * Get the inverse JDORelationship in the case of a two-way relationship.
  216        * @return the inverse relationship
  217        */
  218       public JDORelationship getInverseRelationship() {
  219           if (inverse != null) {
  220               // return inverse relationship, if explicitly set by the setter
  221               return inverse;
  222           }
  223   
  224           // not set => check inverse name 
  225           String fieldName = getInverseRelationshipName();
  226           if (fieldName != null) {
  227               JDOClass relatedClass = getRelatedJDOClass();
  228               JDOField relatedField = relatedClass.getField(fieldName);
  229               if (relatedField != null)
  230                   return relatedField.getRelationship();
  231           }
  232           return null;
  233       }
  234   
  235       /**
  236        * Set the inverse JDORelationship in the case of a two-way relationship.
  237        * The two relationship elements involved are set as inverses of each 
  238        * other and the old inverse is unset.
  239        * <p>
  240        * Warning: this methods casts the existing and the specified inverse
  241        * relationship instance to JDORelationshipImpl.
  242        * @param inverseRelationship the inverse relationship
  243        */
  244       public void setInverseRelationship(JDORelationship inverseRelationship) 
  245           throws ModelException {
  246           
  247           // Skip setting the inverse, if already it is set to the specified
  248           // instance. Note, do not use the result of getInverseRelationship for
  249           // this check, since it might calculate an inverse relationship
  250           // instance that is identical to the specified one, although the
  251           // inverse is not yet set.
  252           if (this.inverse == inverseRelationship) {
  253               return;
  254           }
  255   
  256           // clear old inverse which still points to here
  257           JDORelationshipImpl old = 
  258               (JDORelationshipImpl) getInverseRelationship();
  259           if (old != null) {
  260               if (this.equals(old.getInverseRelationship()))
  261                   old.changeInverseRelationship(null);
  262           }
  263   
  264           // link from here to new inverse
  265           changeInverseRelationship(inverseRelationship);
  266   
  267           // link from new inverse back to here
  268           if (inverseRelationship != null) {
  269               ((JDORelationshipImpl) inverseRelationship).
  270                   changeInverseRelationship(this);
  271           }
  272       }
  273   
  274       /**
  275        * Determines whether this side of a two-way relationship is the
  276        * owning side.
  277        * @return <code>true</code> if this side is the owning side;
  278        * <code>false</code> otherwise. 
  279        */
  280       public boolean isOwner() {
  281           return getMappedBy() == null;
  282       }
  283   
  284       /**
  285        * Determines whether this JDORelationship represents a reference
  286        * relationship or not. A return of <code>true</code> means this
  287        * JDORelationship is a JDOReference instance.
  288        * @return <code>true</code> if this JDORelationship represents a
  289        * reference relationship; <code>false</code> otherwise.
  290        */
  291       public boolean isJDOReference() {
  292           return false;
  293       }
  294       
  295       /**
  296        * Determines whether this JDORelationship represents a collection
  297        * relationship or not. A return of <code>true</code> means this
  298        * JDORelationship is a JDOCollection instance.
  299        * @return <code>true</code> if this JDORelationship represents a
  300        * collection relationship; <code>false</code> otherwise.
  301        */
  302       public boolean isJDOCollection() {
  303           return false;
  304       }
  305   
  306       /**
  307        * Determines whether this JDORelationship represents an array
  308        * relationship or not. A return of <code>true</code> means this
  309        * JDORelationship is a JDOArray instance.
  310        * @return <code>true</code> if this JDORelationship represents an 
  311        * array relationship; <code>false</code> otherwise.
  312        */
  313       public boolean isJDOArray() {
  314           return false;
  315       }
  316   
  317       /**
  318        * Determines whether this JDORelationship represents a map 
  319        * relationship or not. A return of <code>true</code> means this
  320        * JDORelationship is a JDOMap instance.
  321        * @return <code>true</code> if this JDORelationship represents a
  322        * map relationship; <code>false</code> otherwise.
  323        */
  324       public boolean isJDOMap() {
  325           return false;
  326       }
  327   
  328       //========= Internal helper methods ==========
  329   
  330       /** 
  331        * Get the type representation of the relationship. This will be 
  332        * the JavaType for references, the element type for collections
  333        * and arrays, and the value type for maps.
  334        * @return the relationship type
  335        */
  336       public abstract JavaType getRelatedJavaType();
  337   
  338       /** Changes the inverse relationship element for this relationship 
  339        * element.
  340        * This method is invoked for both sides from
  341        * {@link #setInverseRelationship} and should handle setting the 
  342        * internal variable.
  343        * @param inverseRelationship - a relationship element to be used as the
  344        * inverse for this relationship element or <code>null</code> if this
  345        * relationship element does not participate in a two-way relationship.
  346        * @exception ModelException if impossible
  347        */
  348       private void changeInverseRelationship(JDORelationship 
  349           inverseRelationship) throws ModelException {
  350           this.inverse = inverseRelationship;
  351           this.inverseName = ((inverseRelationship == null) ? null :
  352               inverseRelationship.getDeclaringField().getName());
  353       }
  354   
  355       /** 
  356        * Returns the UnresolvedRelationshipHelper instance from the declaring
  357        * field.
  358        * @return the current UnresolvedRelationshipHelper
  359        */
  360       private UnresolvedRelationshipHelper getUnresolvedRelationshipHelper() {
  361           return ((JDOFieldImplDynamic) getDeclaringField()).
  362               getUnresolvedRelationshipHelper();
  363       }    
  364   }

Save This Page
Home » jdo2-model-2.3-ea-src » org.apache.jdo.impl.model.jdo » [javadoc | source]