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 }