View Javadoc

1   /*
2    * Copyright 2006-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sourceforge.domian.repository;
17  
18  
19  import java.util.Map;
20  import java.util.Set;
21  
22  import net.sourceforge.domian.entity.Entity;
23  import net.sourceforge.domian.specification.Specification;
24  
25  
26  /**
27   * Interface for specification-based partitioned repositories.
28   * <p/>
29   * Partitioned repositories will not consist of a single repository instance,
30   * but rather a directed acyclic graph (DAG) of repository instances.
31   * Each repository partition is defined by a {@link net.sourceforge.domian.specification.Specification},
32   * and these partitions are organized following the semantics of <i>specification subsumptions</i>.
33   * <p/>
34   * One might regard partitions as repository <i>indices</i>,
35   * and the routine of adding them as <i>indexing</i> the overall repository.
36   * <p/>
37   * There are some known weaknesses for partitioned repositories.
38   * When entity state changes, <i>before the entity is updated/repartitioned</i>, its whereabouts in the overall repository structure is unstable.
39   * For instance:
40   * <ul>
41   * <li/>When finding entities based on specifications exactly matching a partition specification, only entities residing in that particular repository will be investigated
42   * <li/>... 
43   * </ul>
44   *
45   * @author Eirik Torske
46   * @see <a href="./../specification/Specification.html#isGeneralizationOf(net.sourceforge.domian.specification.Specification)">Specifications subsumption <code>generalizationOf</code></a>
47   * @see <a href="./../specification/Specification.html#isSpecialCaseOf(net.sourceforge.domian.specification.Specification)">Specifications subsumption <code>specialCaseOf</code></a>
48   * @since 0.4
49   */
50  public interface PartitionRepository<T extends Entity> extends Repository<T> {
51  
52      /** @return the type of entities residing in this repository */
53      Class<T> getType();
54  
55      /**
56       * <i>This method applies to this partition only!</i>
57       *
58       * @return <code>true</code> if this repository partition is the root partition (does not have a super partitions)
59       */
60      Boolean isRootPartition();
61  
62      /** @return the root repository of this partitioned repository graph */
63      PartitionRepository<? super T> getRootRepository();
64  
65      /**
66       * <i>This method applies to this partition only!</i>
67       *
68       * @return <code>true</code> if this repository partition is a leaf partition (does not have any sub partitions)
69       */
70      Boolean isLeafPartition();
71  
72      /**
73       * Adds a new partition to this repository.
74       * The partition is specified (indexed) by a {@link net.sourceforge.domian.specification.Specification}.
75       * The new partition repository will be of the same type as this repository.
76       *
77       * @param partitionSpecification the specification specifying the partition
78       * @return the newly created partition
79       */
80      <V extends T> PartitionRepository<V> addPartitionFor(Specification<V> partitionSpecification);
81  
82      /**
83       * Adds a new partition to this repository.
84       * The partition is specified (indexed) by a {@link net.sourceforge.domian.specification.Specification}.
85       * The new partition repository will be of the same type as this repository.
86       *
87       * @param partitionSpecification the specification specifying the partition
88       * @param repositoryId           the repository id; a non-blank value is mandatory for all persistent repositories
89       * @return the newly created partition
90       */
91      <V extends T> PartitionRepository<V> addPartitionFor(Specification<V> partitionSpecification, String repositoryId);
92  
93      /**
94       * Adds a new partition to this repository.
95       * The partition is specified (indexed) by a {@link net.sourceforge.domian.specification.Specification}.
96       *
97       * @param partitionSpecification the specification specifying the partition
98       * @param partitionRepository    the partition repository
99       * @return the newly created partition
100      */
101     <V extends T> PartitionRepository<V> addPartitionFor(Specification<V> partitionSpecification, Repository<? super V> partitionRepository);
102 
103     // TODO: add when needed
104     //<V extends T> void removePartitionFor(Specification<V> partitionSpecification);
105 
106     /**
107      * When an entity is altered, this method must be explicitely invoked to reassure proper placement in the repository partition hierarchy.
108      * <p/>
109      * If any repository implementation does this implicitly in some fashion, this should be documented, e.g. in the Javadoc.
110      *
111      * @param entity the entity to be repartitioned
112      * @return <code>true</code> if entity was repartitioned
113      */
114     <V extends T> Boolean repartition(V entity);
115 
116     /** Repartitions the entire repository. */
117     void repartition();
118 
119     /**
120      * @param specification sub-partition specification
121      * @return the most specialized generalization of the specified partition (possibly this partition
122      */
123     // TODO: generics?
124     <V extends T> PartitionRepository findPartitionFor(Specification<V> specification);
125 
126     // TODO: hmmm, what about multiple repository implementations...? yepp, this is futile!
127     /**
128      * @return <code>true</code> if common repository is used by all partitions,
129      *         and an external indexing scheme is used to ...
130      */
131     //Boolean isUsingExternalIndexingAsPartitioningMechanism();
132 
133     /**
134      * <i>This method applies to this partition only!</i>
135      *
136      * @return the specification defining the super partition
137      */
138     //Specification<? super T> getSuperPartitionSpecification();
139 
140     /** <i>This method applies to this partition only!</i> */
141     void setSuperPartitionSpecification(Specification<? super T> specification);
142 
143     /**
144      * <i>This method applies to this partition only!</i>
145      *
146      * @return the repository in the super partition
147      */
148     PartitionRepository<? super T> getSuperPartitionRepository();
149 
150     /** <i>This method applies to this partition only!</i> */
151     void setSuperPartitionRepository(PartitionRepository<? super T> specification);
152 
153     /**
154      * <i>This method applies to this partition only!</i>
155      *
156      * @return the specification defining this partition
157      */
158     Specification<T> getPartitionSpecification();
159 
160     /** <i>This method applies to this partition only!</i> */
161     void setPartitionSpecification(Specification<T> specification);
162 
163     /**
164      * <i>This method applies to this partition only!</i>
165      * <p/>
166      * <i>
167      * This method is a ( at the moment) necessary workaround for missing functionality regarding runtime modification of the {@code Repository} instance.
168      * Not only the {@code Repository} instance in action must be modified, <b>but all super partitions leading up to the root repository as well</b>.
169      * Is it possible anyway...?
170      * </i>
171      *
172      * @return the delegated repository instance for this partition if any; otherwise {@code null}
173      */
174     Repository<T> getTargetRepository();
175 
176     /**
177      * <i>This method applies to this partition only!</i>
178      *
179      * @return a set of all entities residing in this particular partition
180      */
181     <V extends T> Set<V> getPartitionOnlyEntities();
182 
183     /**
184      * <i>Optional: mainly added for testing purposes, may throw {@link UnsupportedOperationException}</i>
185      * <p/>
186      * <i>This method applies to this partition only!</i>
187      *
188      * @return the direct sub-partitions of this {@link PartitionRepository} only
189      * @throws UnsupportedOperationException if not supported
190      */
191     Map<Specification<? extends T>, PartitionRepository> getPartitions();
192     // TODO v0.5.x: what about
193     //Map<Specification<? extends T>, PartitionRepository<? super T>> getPartitions();
194 
195     /**
196      * <i>Optional: mainly added for testing purposes, may throw {@link UnsupportedOperationException}</i>
197      *
198      * @return a flattened view of all sub-partitions from this {@link PartitionRepository} and below
199      * @throws UnsupportedOperationException if not supported
200      */
201     Map<Specification<? extends T>, PartitionRepository> getAllPartitions();
202     // TODO v0.5.x: what about
203     //Map<Specification<? extends T>, PartitionRepository<? super T>> getAllPartitions();
204 
205     /**
206      * Populates the given map with a flattened and recursive view of all partitions in this repository.
207      * <p/>
208      * <i>Optional: mainly added for testing purposes, may throw {@link UnsupportedOperationException}</i>
209      *
210      * @param partitionMap the index->partition map
211      * @throws IllegalArgumentException      if the partition map is <code>null</code>
212      * @throws UnsupportedOperationException if not supported
213      */
214     void collectAllPartitions(Map<Specification<? extends T>, PartitionRepository> partitionMap);
215     // TODO v0.5.x: what about
216     //void collectAllPartitions(Map<Specification<? extends T>, PartitionRepository<? super T>> partitionMap);
217 
218     /**
219      * Populates the given map with a flattened and recursive view of all partitions in this repository,
220      * satisfying the given specification.
221      * <p/>
222      * <i>Optional: mainly added for testing purposes, may throw {@link UnsupportedOperationException}</i>
223      *
224      * @param specification the specification to satisfy to be included in result map
225      * @param partitionMap  the index->partition map
226      * @throws IllegalArgumentException      if the partition map is <code>null</code>
227      * @throws UnsupportedOperationException if not supported
228      */
229     <R extends Repository> void collectAllPartitionsWithRepositorySatisfying(Specification<R> specification,
230                                                                              Map<Specification<? extends T>, PartitionRepository> partitionMap);
231 }