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РР