jsr338-experts@jpa-spec.java.net

[jsr338-experts] Re: Proposal for EntityGraphs, fetch plans, etc...

From: Pinaki Poddar <ppoddar_at_us.ibm.com>
Date: Wed, 28 Nov 2012 12:32:59 -0800

Thank you for bringing Fetch Plan for discussion and an extensive proposal
to realize it.

Few comments:
1. The naming could be FetchPlan/FetchAttribute etc as they are more
commonly used than NamedEntityGraph etc.

2. The need for a SubGraph may not be required. If every
FetchGroup/NamedEntityGraph defined/rooted in entity type X can include
FetchGroup(s) defined in other entity type Y, then a separate definition of
SubGraph would not be necessary.

3. The fetch attributes can simply be persistent property names (i.e.
Strings) to reduce verbosity of annotations/XML descriptors. The type
information is already available through MetaModel and entity type
definitions, so why would the graph specification require them?

4. A concept of recursion depth is required on relationship paths to
control the cycles in a graph.

5. With our usage of Fetch Plans, we found it useful to control the maximum
fetch depth (counted as a number of edges from the root to a leaf node
being fetched)

6. A lock specification could be an optional qualifier on relation paths

Regards --

Pinaki Poddar
Chair, Apache OpenJPA Project http://openjpa.apache.org/
JPA Expert Group Member
Application & Integration Middleware








From: Gordon Yorke <gordon.yorke_at_oracle.com>
To: jsr338-experts_at_jpa-spec.java.net
Date: 11/28/2012 05:32 AM
Subject: [jsr338-experts] Re: Proposal for EntityGraphs, fetch plans,
            etc...



Hello All,
   Based on suggestions from a colleague I would like to suggest some
clarification and updates.
   1 - with respect to @Version add to the proposal that version is always
fetched and copied along with the PK.

   2 - Add :
    /**
     * returns all named EntityGraphs that have been defined for the
provided
     * class type.
     */
    public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T>
entityClass);

   3 - Fix EntityManager.copy :
    public <X> X copy(X entity, EntityGraph<? super X> entityGraph,
Map<String, Object> properties);

Thank you,
--Gordon


On 27/11/2012 5:20 PM, Gordon Yorke wrote:
      Hello all,
         Please find below a proposal for EntityGraphs and their use to
      define entity graph fetching, loading, merging and copying. I have
      been working with Mike Keith and Linda DeMichiel on this proposal and
      we feel it is time to present to the expert group. Please have a
      look and provide feedback as the intention is to integrate this
      within the 2.1 spec.
      Thank you,
      Gordon

      ----
      A common functional request has been to enable users to dynamically
      define how an EntityManager operation or query should apply to an
      entity graph. This may more commonly be known as “merge groups” or
      “fetch plans”. This functionality can be especially important when
      detached entities must be serialized and then merged into an active
      Persistence Context.

      An entity graph is a template defined in the form of metadata or an
      object created by the dynamic EntityGraph API that captures the path
      and boundaries for an operation or a query For static metadata the
      NamedEntityGraph annotation defines the attribute nodes and
      boundaries of the grouping.

      @Target({TYPE})
      @Retention(RUNTIME)
      public @interface NamedEntityGraphs{
          NamedEntityGraph[] value();
      }

      @Target({TYPE})
      @Retention(RUNTIME)
      public @interface NamedEntityGraph{
          /**
           * (Optional) The name of the sub-graph.
           * Defaults to the entity name of the root entity.
           */
          String name() default "";

          /**
           * (Required) list of attributes that are included in in this
      sub-graph.
           */
          NamedAttributeNode[] attributeNodes();

          /**
           * (Optional) Lists all of the attributes of this Entity class to
      be listed in
           * the NamedEntityGraph without the need to explicitly list them.
      Included
           * attributes can still be fully specified by an attribute node
      referencing a
           * sub-graph.
           */
          boolean includeAllAttributes() default false;

          /**
           * (Optional) This is a list of sub-graphs that are included in
      the
           * entity graph. They are referenced by name from
      NamedAttributeNode
           * definitions.
           */

          NamedSubGraph[] subGraphs() default {};

          /**
           * (Optional) This is a list of sub-graphs that will add
      additional attributes
           * for subclasses of the entity represented by this
      NamedEntityGraph to this
           * entity graph. Specified attributes from superclasses are
      included in
           * subclasses.
           */

          NamedSubGraph[] subclassSubGraphs() default {};
      }

      The NamedEntityGraph annotation is applied to an Entity class that is
      defined as the root of a group of attributes, relationships and
      related entity classes. The NamedAttributeNode annotations are
      embedded within the NamedEntityGraph metadata and define the
      attributes of the entity that are included in the grouping. When a
      NamedAttributeNode represents an Entity or an Embedded (including a
      collection-valued relationship or an element collection of
      embeddables), the referenced type’s attributes can be included as a
      NamedSubGraph entry of the entity graph and referenced by name,
      creating a multi-level entity graph. If the sub-graph represents an
      entity with inheritance multiple NamedSubGraph entries can be made
      with the same name to extend the sub-graph for specific subclasses.
      The class type that is being extended is required in the
      NamedSubGraph.

      /**
       * A NamedAttributeNode is a member attribute of a NamedEntityGraph.
       *
       * @see javax.persistence.NamedEntityGraph
       * @see javax.persistence.NamedSubGraph

      */
      @Target({})
      @Retention(RUNTIME)
      public @interface NamedAttributeNode {
          /**
           * (Required) the name of the attribute that must be in the
      sub-graph.
           */
          String value();

          /**
           * (Optional) if this attribute references a managed type that
      has its own
           * AttributeNodes then this refers to that NamedSubGraph
      definition. If the
           * target type has inheritance than multiple sub graphs can be
      specified.
           * These additional sub-graphs are intended to add additional
      attributes from
           * subclasses. Superclass sub-graph entries will be merged into
      subclasses
           * sub-graphs.
           */
          String subGraph() default “”;

         /**
          * (Optional) if the attribute references a Map type this can be
      used to specify
          * a subGraph for the Key in the case of an Entity key type. A
          * keySubGraph can not be specified without the Map attribute also
      being
          * specified. If the target type has inheritance than multiple
      sub-graphs can
          * be specified. These additional sub-graphs are intended to add
      additional
          * attributes from subclasses. Superclass sub-graph entries will
      be merged
          * into subclasses sub-graphs.
          */
          String keySubGraph() default "";

      }

      /**
       * A NamedSubGraph is a member of a NamedEntityGraph that represents
      a managed
       * type. The NamedSubGraph is only referenced from within a
      NamedEntityGraph and
       * can not be referenced on its own. It is referenced by name from a
       * NamedAttributeNode of the NamedEntityGraph.
       *
       * @see javax.persistence.NamedEntityGraph
      * @see javax.persistence.NamedAttributeNode
       */
      @Target({})
      @Retention(RUNTIME)
      public @interface NamedSubGraph {
          /**
           * (Required) the name of the sub-graph as referenced from a
           * NamedAttributeNode.
           */
          String name();

          /**
           * (Optional) the type represented by this subgraph. Required
      when this
           * subgraph is extending a subclass’ definition.
           */
          Class type default void.class;

          /** (Required)
           * if this NamedAttributeNode references a managed type then this
      list is
           * the attributes of that type that must be included.
           */
          NamedAttributeNode[] attributeNodes();

      }

      For example:
      @Entity
      public class Employee{

        @Id
        @GeneratedValue
        protected long id;

        @Basic
        protected String name;

        @Basic
        protected String employeeNumber;

        @OneToMany()
        protected List<Dependants> dependants;

        @OneToMany()
        protected List<Project> projects;

        @OneToMany()
        protected List<PhoneNumber> phoneNumbers;
        ...
      }

      @Entity
      @Inheritance
      public class Project{
          @Id
          @GeneratedValue
          protected long id;

          @OneToOne(fetch=FetchType.EAGER)
          protected Requirements doc;
         ...
      }

      @Entity
      public class LargeProject extends Project{

          @OneToOne(fetch=FetchType.LAZY)
          protected Employee approver;
         ...
      }

      @Entity
      public class Phonenumber{
          @Id
          protected String number;

          protected PhoneTypeEnum type;
         ...
      }

      @Entity
      public class Requirements{
          @Id
          protected long id;

          @Lob
          protected String description;

          @OneToOne(fetch=FetchType.LAZY)
          protected Approval approval
         ...
      }

      @NamedEntityGraph(
          attributeNodes={
              @NamedAttributeNode(
                  value="projects",
                  subGraph=”projects”
              ),
              @NamedttributeNode(name = "phoneNumbers"),
          },
          subGraphs={
              @NamedSubGraph(
                  name=”projects”,
                  attributeNodes={
                      @NamedAttributeNode("requirements")
                  }
              ),
              @NamedSubGraph(
                  name=”projects”,
                  type=LargeProject.class,
                  attributeNodes={
                      @NamedAttributeNode("approver")
                  }
              )
          }
      )

      @NamedEntityGraph(
          name-”Project”,
          attributeNodes={
              @NamedAttributeNode("requirements")
          },
          subclassSubGraphs={
              @NamedSubGraph(
                  type=LargeProject.class,
                  attributeNodes={
                      @NamedAttributeNode("approver")
                  }
              )
          }
      )

      @NamedEntityGraph(
          name="EmployeeProjectRequirements"
          attributeNodes={
              @NamedAttributeNode(
                  value="projects",
                  subGraph=”projects”
              ),
              @NamedttributeNode(name = "phoneNumbers"),
          },
          subGraphs={
              @NamedSubGraph(
                  name=”projects”,
                  attributeNodes={
                      @NamedAttributeNode(
                           value ="requirements",
                           subGraph=”requirements”
                      )
                  }
              ),
              @NamedSubGraph(
                  name=”requirements”,
                  attributeNodes={
                      @NamedAttributeNode("description"),
                      @NamedAttributeNode("approval")
                  }
              )
          }
      )

      The entity graph could also be created dynamically through the
      following APIs:

      /**
       * This type represents the root of an entity graph that will be used
      as a
       * template to define the attribute nodes and boundaries of a graph
      of entities and
       * entity relationships. The root must be an Entity type.
       *
       * @param <T>
       * the type of the root entity.
       */

      public interface EntityGraph<T> {

          /**
           * Returns the name of the static EntityGraph. Will return null
      if the
           * EntityGraph is not a named EntityGraph.
           */
          public String getName();

          /*
           * Add an AttributeNode attribute to the entity graph.
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this entity.
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> void addAttributeNodes(String ... attributeName);

          /*
           * Add an AttributeNode attribute to the entity graph.
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> void addAttributeNodes(Attribute<T, X> ... attribute);

          /*
           * Used to add a node of the graph that corresponds to a managed
      type. This
           * allows for construction of multi-node Entity graphs that
      include related
           * managed types.
           *
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addSubGraph(Attribute<T, X> attribute);

          /**
           * Used to add a node of the graph that corresponds to a managed
      type with
           * inheritance. This allows for multiple subclass sub-graphs to
      be defined
           * for this node of the entity graph. Subclass sub-graphs will
      include the
           * specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException
           * if the attribute's target type is not a managed
      type
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> SubGraph<? extends X> addSubGraph(Attribute<T, X>
      attribute, Class<? extends X> type);

          /*
           * Used to add a node of the graph that corresponds to a managed
      type. This
           * allows for construction of multi-node Entity graphs that
      include related
           * managed types.
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this entity.
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addSubGraph(String attribute);

          /**
           * Used to add a node of the graph that corresponds to a managed
      type with
           * inheritance. This allows for multiple subclass sub-graphs to
      be defined
           * for this node of the entity graph. Subclass sub-graphs will
      include the
           * specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this managed type.
           * @throws IllegalArgumentException
           * if the attribute's target type is not a managed
      type
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> SubGraph<X> addSubGraph(String attribute, Class<X>
      type);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type. This allows for construction of multi-node
      Entity graphs that
           * include related managed types.
           *
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type entity
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addKeySubGraph(Attribute<T, X> attribute);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type with inheritance. This allows for construction of
      multi-
           * node Entity graphs that include related managed types.
      Subclass sub-graphs
           * will include the specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type entity

           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<? Extends X> addKeySubGraph(Attribute<T, X>
      attribute, Class<? Extends X> type);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type. This allows for construction of multi-node
      Entity graphs that
           * include related managed types.
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this entity.
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addKeySubGraph(String attribute);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type with inheritance. This allows for construction of
      multi-
           * node Entity graphs that include related managed types.
      Subclass sub-graphs
           * will include the specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this entity.
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addKeySubGraph(String attribute, Class<X>
      type);

          /*
           * returns the attributes of this entity that are included in the
      entity
           * graph
           */
          public List<AttributeNode<?>> getAttributeNodes();

      }

      /**
       * Represents an AttributeNode of an entity graph.
       */
      public interface AttributeNode<T> {

          /*
           * returns the Type of the AttributeNode.
           */


          public Type<T> getType();

          /*
           * returns the name of the referencing attribute.
           */
          public String getAttributeName();
      }

      /**
       * This type represents a AttributeNode of an EntityGraph that
      corresponds to a
       * Managed Type. Using this class an entity graph can be embedded
      within an
       * EntityGraph.
       *
       * @param <T>
       * the Class type of the AttributeNode.
       */

      public interface SubGraph<T> extends AttributeNode<T> {

          /**
           * Add an AttributeNode attribute to the entity graph.
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this managed type.
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> void addAttributeNodes(String ... attributeName);

          /**
           * Add an AttributeNode attribute to the entity graph.
           *
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> void addAttributeNodes(Attribute<T, X> ... attribute);

          /**
           * Used to add a node of the graph that corresponds to a managed
      type. This
           * allows for construction of multi-node Entity graphs that
      include related
           * managed types.

           *
           * @throws IllegalArgumentException
           * if the attribute's target type is not a managed
      type
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> SubGraph<X> addSubGraph(Attribute<T, X> attribute);

          /**
           * Used to add a node of the graph that corresponds to a managed
      type with
           * inheritance. This allows for multiple subclass sub-graphs to
      be defined
           * for this node of the entity graph. Subclass sub-graphs will
      include the
           * specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException
           * if the attribute's target type is not a managed
      type
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> SubGraph<? extends X> addSubGraph(Attribute<T, X>
      attribute, Class<? extends X> type);

          /**
           * Used to add a node of the graph that corresponds to a managed
      type. This
           * allows for construction of multi-node Entity graphs that
      include related
           * managed types.
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this managed type.
           * @throws IllegalArgumentException
           * if the attribute's target type is not a managed
      type
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> SubGraph<X> addSubGraph(String attribute);

          /**
           * Used to add a node of the graph that corresponds to a managed
      type with
           * inheritance. This allows for multiple subclass sub-graphs to
      be defined
           * for this node of the entity graph. Subclass sub-graphs will
      include the
           * specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this managed type.
           * @throws IllegalArgumentException
           * if the attribute's target type is not a managed
      type
           * @throws IllegalStateException
           * if this EntityGraph has been statically defined
           */
          public <X> SubGraph<X> addSubGraph(String attribute, Class<X>
      type);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type. This allows for construction of multi-node
      Entity graphs that
           * include related managed types.
           *
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type entity

           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addKeySubGraph(Attribute<T, X> attribute);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type with inheritance. This allows for construction of
      multi-
           * node Entity graphs that include related managed types.
      Subclass sub-graphs
           * will include the specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type entity

           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<? Extends X> addKeySubGraph(Attribute<T, X>
      attribute, Class<? Extends X> type);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type. This allows for construction of multi-node
      Entity graphs that
           * include related managed types.
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this entity.
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addKeySubGraph(String attribute);

          /*
           * Used to add a node of the graph that corresponds to a map key
      that is a
           * managed type with inheritance. This allows for construction of
      multi-
           * node Entity graphs that include related managed types.
      Subclass sub-graphs
           * will include the specified attributes of superclass sub-graphs
           *
           * @throws IllegalArgumentException if the attribute is not an
      attribute of
           * this entity.
           * @throws IllegalArgumentException if the attribute's target
      type is not a
           * managed type
           *
           * @throws IllegalStateException if this EntityGraph has been
      statically
           * defined
           */
          public <X> SubGraph<X> addKeySubGraph(String attribute, Class<X>
      type);

          /**
           * returns the attributes of this managed type that are included
      in the
           * sub-graph
           */
          public List<AttributeNode<?>> getAttributeNodes();

          /**
           * returns the attribute that references this sub-graph.
           /
          public <T> Attribute<T,X> getReferencingAttribute();

          /**
           * returns the type of this sub-graph if it was used to extend a
      superclass’
           * sub-graph definition.
           */
          public Class<X> getClassType();
      }

      public interface EntityManagerFactory {
           ...
          /**
           * returns any named EntityGraph that has been created through
      static
           * metadata. Returned EntityGraphs should be considered
      immutable.
           */
          public <T> EntityGraph<T> getEntityGraph(String graphName);

          /**
           * add a named copy of the EntityGraph to the
      EntityManagerFactory
           */
          public void addNamedEntityGraph(String graphName, EntityGraph
      entityGraph);

          /**
           * returns a mutable EntityGraph that can be used to dynamically
      create an
           * EntityGraph.
           */
          public <T> EntityGraph<T> createEntityGraph(Class<T> rootType);

          /**
           * returns a mutable copy of the named EntityGraph
           */
          public EntityGraph<?> createEntityGraph(String graphName);

      Example:

            EntityGroup employee = emf.createEntityGraph(Employee.class);
         employee.addAttributeNode("phoneNumbers");
         SubGraph projects = employee.addSubGraph("projects");
         projects.addAttributeNode("requirements");
         SubGraph largeProjects = employee.addSubGraph(“projects”,
      LargeProject.class);
         largeProjects.addAttributeNode(“approver”);

         EntityGroup employee = emf.createEntityGraph(Employee.class);
         employee.addAttributeNode("phoneNumbers");
         SubGraph requirements = employee.addSubGraph("projects")
                                             .addSubGraph("requirements");
         requirements.addAttributeNode("description");
         requirements.addAttributeNode("approval");

      Once the EntityGraph is available or has been created it can be
      applied to operations on the EntityManager or used with queries to
      control eager loading of results.

      The standard property javax.persistence.fetchgraph can be used with
      the find operation or as a query hint to specify a EntityGraph that
      defines additional FetchType semantics whereby any AttributeNode of
      the EntityGraph is treated as FetchType.EAGER and any attribute not
      specified in the EntityGraph is treated as FetchType.LAZY. The
      primary key of an entity is always retrieved even if not present in
      the fetch group.

      The following characterizes the semantics of entity graphs that are
      used as fetch graphs.

      A fetch graph attribute node specified within an entity graph or
      sub-graph specifies how an attribute is to be fetched. Attributes
      that are not specified are treated as FetchType.LAZY.

      The following rules apply, depending on attribute type.

      A primary key attribute never needs to be specified in an attribute
      node. (This applies to composite primary keys as well, including
      embedded id primary keys.) When an entity is fetched, its primary
      key is always fetched. It is not incorrect, however, to specify
      primary key attributes.

      Attributes other than primary key attributes are not fetched unless
      the attribute is specified. The following rules apply to the
      specification of attributes:

      The default fetch graph for an entity or embeddable consists of the
      transitive closure of all of its attributes that are specified as
      FetchType.EAGER (or defaulted as such).

      If the attribute is an embedded attribute, and the attribute is
      specified in an attribute node, but a subgraph is not specified for
      the attribute, the default fetch graph for the embeddable is fetched.
      If a subgraph is specified for the attribute, the attributes of the
      embeddable are fetched according to their specification in the
      corresponding subgraph, and the rules of this section recursively
      apply.

      If the attribute is an element collection of basic type, and the
      attribute is specified in an attribute node, the element collection
      together with its basic elements is fetched.

      If the attribute is an element collection of embeddables, and the
      attribute is specified in an attribute node, but a subgraph is not
      specified for the attribute, the element collection together with the
      default fetch graph of its embeddable elements is fetched. If a
      subgraph is specified for the attribute, the attributes of the
      embeddable elements will be fetched according to the corresponding
      subgraph specification, and the rules of this section recursively
      apply.

      If the attribute is a one-to-one or many-to-one relationship, and the
      attribute is specified in an attribute node, but a subgraph is not
      specified for the attribute, the default fetch graph of the target
      entity is fetched. If a subgraph is specified for the attribute, the
      attributes of the target entity will be fetched according to the6'&W7Fr7V&w&7V6f6FBFR'VW2bF26V7FТ&V7W'6fVǒǒРТbFRGG&'WFR2RF"F&VF6@ТFRGG&'WFR27V6fVBGG&'WFRFR'WB7V&w&0ТB7V6fVBFR6V7Fv&RfWF6VBBFRFVfVBfWF6Тw&2bFR&VfW&V6VBVFFW2v&RfWF6VBb7V&w&0Т7V6fVBf"FRGG&'WFRFRVFFW2FR6V7Fv&PТfWF6VB66&FrFFR6'&W7Fr7V&w&7V6f6F@ТFR'VW2bF26V7F&V7W'6fVǒǒРТbFRWbv62&VV7V6fVBGG&'WFRFR0Т&62GRBvv2&RfWF6VBBbFRWbv6Т2&VV7V6fVBGG&'WFRFR2V&VFFVBGRFPТFVfVBfWF6w&v&RfWF6VBf"FRV&VFF&SFW'v6R`ТW7V&w&2B7V6fVBf"FRGG&'WFRFRFRFG2FVfVBfWF6w&bWТ7V&w&27V6fVBf"FRWGG&'WFRFRWТGG&'WFRv&RfWF6VB66&FrFFRW7V&w&Т7V6f6FBFR'VW2bF26V7F&V7W'6fVǒǒРТ6W6rFRfvrVFGw&РТVDVFGw&ТРТW6VBFBVV&W"ǒFRBBFRd2vVB&PТ&WG&WfVBРТvVW6rFRfvrVFGw&ТVDVFGw&ТGG&'WFTFW3װТVDGG&'WFTFR'&V7G2"ТТРТFrVVRFR2Bd2vVB&R&WG&WfVBBFPТ( &V7G>( GG&'WFRvVB&RVvW&ǒFVBРТFR7FF&B&W'GfW'67FV6RFw&6&RW6VBFТ7V6gVFGw&FBFVfW2FFFfWF6GR6VF70ТvFGG&'WFRFRbFRVFGw&&V6֖rfWF6GRTtU ТBV7V6fVBGG&'WFW2&V2FVfVBFRrРТFRfvr6&7FW&W2FR6VF72bVFGw&2FB&PТW6VB2Bw&2РТBw&GG&'WFRFR7V6fVBvFVFGw& Т7V"w&7V6fW2rGG&'WFR2F&RfWF6VBGG&'WFW0ТFB&RB7V6fVB&RG&VFVB66&FrFFV"FVfV@ТfWF6GRРТFRfvr'VW2ǒFFR7V6f6FbGG&'WFW3РТ&'WGG&'WFRWfW"VVG2F&R7V6fVBGG&'WFPТFRF2ƖW2F66FR&'W22vV6VFpТV&VFFVBB&'W2vVVFG2fWF6VBG2&'ТW2v2fWF6VBB2B6'&V7BvWfW"F7V6gТ&'WGG&'WFW2РТbFRGG&'WFR2V&VFFVBGG&'WFRBFRGG&'WFR0Т7V6fVBGG&'WFRFR'WB7V&w&2B7V6fVBf ТFRGG&'WFRFRFVfVBfWF6w&f"FRV&VFF&R2fWF6VBТb7V&w&27V6fVBf"FRGG&'WFRGG&'WFW2bFPТV&VFF&RFB&RBgW'FW"7V6fVBvFFR7V&w&&PТG&VFVB66&FrFFV"fWF6GSGG&'WFW2FB&R7V6fV@Т'FR7V&w&&R6fWF6VCBFR'VW2bF26V7FТ&V7W'6fVǒǒРТbFRGG&'WFR2VVVB6V7Fb&62GRBFPТGG&'WFR27V6fVBGG&'WFRFRFRVVVB6V7FТFvWFW"vFG2&62VVVG22fWF6VBbFRGG&'WFR2ТVVVB6V7FbV&VFF&W2BFRGG&'WFR27V6fVBТGG&'WFRFR'WB7V&w&2B7V6fVBf"FRGG&'WFRТFRVVVB6V7FFvWFW"vFFRFVfVBfWF6w&bG0ТV&VFF&RVVVG22fWF6VBb7V&w&27V6fVBf"FPТGG&'WFRGG&'WFW2bFRV&VFF&W2FB&RBgW'FW Т7V6fVB&RG&VFVB66&FrFFV"fWF6GSGG&'WFW2F@Т&R7V6fVB'FR7V&w&&R6fWF6VCBFR'VW2bF0Т6V7F&V7W'6fVǒǒРТbFRGG&'WFR2RFR"FR&VF6BFPТGG&'WFR27V6fVBGG&'WFRFR'WB7V&w&2@Т7V6fVBf"FRGG&'WFRFRFVfVBfWF6w&bFRF&vW@ТVFG2fWF6VBb7V&w&27V6fVBf"FRGG&'WFRТGG&'WFW2bFRF&vWBVFGFB&RBgW'FW"7V6fVB&PТG&VFVB66&FrFFV"fWF6GSGG&'WFW2FB&R7V6fV@Т'FR7V&w&&R6fWF6VCBFR'VW2bF26V7FТ&V7W'6fVǒǒРТbFRGG&'WFR2RF"F&VF6@ТFRGG&'WFR27V6fVBGG&'WFRFR'WB7V&w&0ТB7V6fVBFR6V7Fv&RfWF6VBBFRFVfVBfWF6Тw&2bFR&VfW&V6VBVFFW2v&RfWF6VBb7V&w&0Т7V6fVBf"FRGG&'WFRVFFW2FR6V7Fv&PТG&VFVB66&FrFFV"fWF6GSGG&'WFW2FB&R7V6fV@Т'FR7V&w&&R6fWF6VCBFR'VW2bF26V7FТ&V7W'6fVǒǒРТb6V7FfVVBGG&'WFR2W2FB&R&62 ТV&VFF&RGW2v&RfWF6VBvVFR2fWF6VCVFGfWF6VB66&FrFFV"fWF6GRB`ТW7V&w&27V6fVBFFFVFGGG&'WFW2&RfWF6V@Т27V6fVBFR7V&w&BFR'VW2bF26V7FТ&V7W'6fVǒǒРТ6W6rFRfvrVFGw&РТVDVFGw&ТРТW6VBFBVV&W"ǒFRBBFRd2vVB&PТ&WG&WfVBFR&WV&VVG2GG&'WFRvVBB&RFVB'WBvV@Т&RРТvVW6rFRfvrVFGw&ТVDVFGw&ТGG&'WFTFW3װТVDGG&'WFTFR'&V7G2"ТТРТFrVVRFR2Bd2vVB&R&WG&WfVBBFPТ( &V7G>( GG&'WFRvVB&RVvW&ǒFVBРТVFGvW"ТV&Ɩ2FW&f6RVFGvW"РТТ6FR&fFVBVFGw&W6rFRVFGw&2ТFVFRFТ7V6gТFRGG&'WFW2FBv&R6VBGG&'WFW2B6VFVBТFRVFGw&vB&R6VBТТ&VFGТVFG7F6PТ&VFGw&ТFRVFGw&FVFRf"ǖr6ТF&w2Vv&wVVDW6WFТbFR7F6R2BVFG"FPТVFGw&&B0ТBFR6R6722FRVFGТТV&Ɩ2fB6&V7BVFGVFGw&VFGw&Т7G&r&V7C&W'FW2ТРТТW&vRFR7FFRbFRvfVVFGFFR7W'&V@ТW'67FV6R6FW@ТW6rFRVFGw&2FVFRf"ǖrFRW&vPТW&FТТТ&VFGТVFG7F6PТ&VFGw&ТFRVFGw&FVFRf"ǖrW&vRТ&WGW&FRvVB7F6RFBFR7FFRv2W&vVBFТF&w2Vv&wVVDW6WFТb7F6R2BVFG2&VfVBVFGТ"FR&@ТbFRVFGw&2BbFR6RGR2FPТVFGТF&w2G&67F&WV&VDW6WFТbFW&R2G&67FvVfVBТ6FW"vVBVFGvW"bFB2`ТGPТ6FSW'67FV6T6FWEGRE$45D6FSТТV&Ɩ2CBW&vRBVFGVFGw&VFGw&7G&rТ&V7C&W'FW2ТWF0ТРТW&vPТvVW6rVFGw&6&FvFFR( W&v^( W&FТƗ7FVBGG&'WFRFRv&RW&vVBBVƗ7FVBGG&'WFPТFRvB&RW&vVBF26VFW2&62w2ТGG&'WFRFB&VfW&V6W2266FW&VBF6VFR&FFRWТBFRfVRbFRGG&'WFRFR&VfW&V6W27V"w&"FR&VF6F&vWBFVFRW&vRvW&FPТFBF&vWB&V7B2vVvFǒF6RGG&'WFW2&VfW&V6V@ТFR7V"w&&VrW&vVBBF2vǒ&V7W'6fVǒРТf"WRvFFRW&vRW&FƖVBvFFRfvpТVFGw&РТVDVFGw&ТGG&'WFTFW3װТVDGG&'WFTFR( ^( ҒТVDGG&'WFTFRТfVS'&V7G2"Т7V$w&( &V7G>( ТТVDGG&'WFTFR'TV&W'2"ТТ7V$w&3װТVE7V$w&ТS( &V7G>( ТGG&'WFTFW3װТVDGG&'WFTFR'&WV&VVG2"ТТТТРТǒFRR&V7G2BTV&W'2GG&'WFW2bFRVVPТv&RW&vVBFRW&vRv&RƖVBFFR&V7G2'WBǐТFR&WV&VVG2GG&'WFRbFR&V7Bv&RW&vVBBFPТW&vRvB&RƖVBFFR&WV&VVBF&vWBFPТTV&W"F&vWBvB&RW&vVBРТ6ТWrW&F( 6( 2&VrG&GV6VBF2W&F0ТFVFVBF&RW6VBvVW6W"v6W2FF66V7Bw&`ТVFFW2g&&vW"w&vVW6rVFGw&Т6&FvFFR( 6( W&F6bFR&fFVBVFGТ27&VFVBBFRGG&'WFW2bFR6VBVFG&RVFV@Т&6VBFRGG&'WFW2Ɨ7FVBFRVFGw&bGG&'WFPТFRf"GG&'WFR2&W6VBFVFRGG&'WFRv&R6VBТbFRGG&'WFRFR&W&W6VG2GG&'WFRFB2vVBGPТ2FRF&vWBVVVB"WGRFVFBF&vWB7F6R0Т6VB2vVBFR626WBFRWrG&VRb7V"w&Т2FVfVBf"FRfVR"WFVGG&'WFW26'&W7FrFТFRGG&'WFRFW2vFFR7V"w&v&R6VB2&fR`Т7V"w&2FVfVBf"FRGG&'WFRFRFVGG&'WFW2`ТFRF&vWB&R6VBРТf"WRvFFR6W&FƖVBvFFRfvrVFGТw&РТVDVFGw&ТGG&'WFTFW3װТVDGG&'WFTFR( ^( ҒТVDGG&'WFTFRТfVS'&V7G2"Т7V$w&( &V7G>( ТТVDGG&'WFTFR'TV&W'2"ТТ7V$w&3װТVE7V$w&ТS( &V7G>( ТGG&'WFTFW3װТVDGG&'WFTFR'&WV&VVG2"ТТТТРТvVƖVBFVVR7F6RWr6bFRVVRvТ&R7&VFVBBFR( ^( ( TV&W'>( B( &V7G>( GG&'WFW0Тv&R6VBfW"f"V6TV&W"FRTV&W'2Ɨ7BТWr6bFRTV&W"v&R7&VFVBBW6VB'WBТGG&'WFW2v&R6VBf"V6&V7BFR&V7G2Ɨ7BТWr6bFR&V7Bv&R7&VFVBBW6VBBǒFPТ&WV&VVG2GG&'WFRv&R6VBf"V6&WV&VVBFPТ&WV&VVG2Ɨ7BWr6bFR&WV&VVBv&R7&VFVB'W@ТGG&'WFW2v&R6VBРР



graycol.gif
(image/gif attachment: graycol.gif)