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 }