00001 /* 00002 * InvocableMap.hpp 00003 * 00004 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_INVOCABLE_MAP_HPP 00017 #define COH_INVOCABLE_MAP_HPP 00018 00019 #include "coherence/lang.ns" 00020 00021 #include "coherence/util/Collection.hpp" 00022 #include "coherence/util/Filter.hpp" 00023 #include "coherence/util/Map.hpp" 00024 #include "coherence/util/QueryMap.hpp" 00025 #include "coherence/util/Set.hpp" 00026 #include "coherence/util/ValueUpdater.hpp" 00027 00028 COH_OPEN_NAMESPACE2(coherence,util) 00029 00030 00031 /** 00032 * Map with additional query features. 00033 * 00034 * @author jh 2008.02.27 00035 */ 00036 class COH_EXPORT InvocableMap 00037 : public interface_spec<InvocableMap, 00038 implements<Map> > 00039 { 00040 // ----- inner interface: Entry ----------------------------------------- 00041 00042 public: 00043 /** 00044 * An InvocableMap::Entry contains additional information and exposes 00045 * additional operations that the basic Map::Entry does not. It allows 00046 * non-existent entries to be represented, thus allowing their 00047 * optional creation. It allows existent entries to be removed from 00048 * the Map. It supports a number of optimizations that can ultimately 00049 * be mapped through to indexes and other data structures of the 00050 * underlying Map. 00051 */ 00052 class COH_EXPORT Entry 00053 : public interface_spec<Entry, 00054 implements<QueryMap::Entry> > 00055 { 00056 // ----- InvocableMap::Entry interface ---------------------- 00057 00058 public: 00059 /** 00060 * Store the value corresponding to this entry. If the entry 00061 * does not exist, then the entry will be created by invoking 00062 * this method, even with a NULL value (assuming the Map 00063 * supports NULL values). 00064 * 00065 * Unlike the other form of {@link #setValue(Object::Holder) 00066 * setValue}, this form does not return the previous value, 00067 * and as a result may be significantly less expensive (in 00068 * terms of cost of execution) for certain Map 00069 * implementations. 00070 * 00071 * @param ohValue the new value for this Entry 00072 * @param fSynthetic pass true only if the insertion into or 00073 * modification of the Map should be 00074 * treated as a synthetic event 00075 * 00076 * @return the prior value 00077 */ 00078 virtual Object::Holder setValue(Object::Holder ohValue, 00079 bool fSynthetic) = 0; 00080 00081 /** 00082 * Update the Entry's value. Calling this method is 00083 * semantically equivalent to: 00084 * <pre> 00085 * Object::Handle hTarget = cast<Object::Handle>( 00086 * hEntry->getValue()); 00087 * vUpdater->update(hTarget, ohValue); 00088 * hEntry->setValue(hTarget, false); 00089 * </pre> 00090 * The benefit of using this method is that it may allow the 00091 * Entry implementation to significantly optimize the 00092 * operation, such as for purposes of delta updates and backup 00093 * maintenance. 00094 * 00095 * @param vUpdater a ValueUpdater used to modify the Entry's 00096 * value 00097 * @param ohValue the new value to use 00098 */ 00099 virtual void update(ValueUpdater::View vUpdater, 00100 Object::Holder ohValue) = 0; 00101 00102 /** 00103 * Determine if this Entry exists in the Map. If the Entry is 00104 * not present, it can be created by calling {@link 00105 * #setValue}. If the Entry is present, it can be destroyed by 00106 * calling {@link #remove}. 00107 * 00108 * @return true iff this Entry is existent in the containing 00109 * Map 00110 */ 00111 virtual bool isPresent() const = 0; 00112 00113 /** 00114 * Remove this Entry from the Map if it is present in the Map. 00115 * This method supports both the operation corresponding to 00116 * Map#remove as well as synthetic operations such as 00117 * eviction. If the containing Map does not differentiate 00118 * between the two, then this method will always be identical 00119 * to calling <tt>remove(getKey())</tt> on the containing Map. 00120 * 00121 * @param fSynthetic pass true only if the removal from the 00122 * Map should be treated as a synthetic 00123 * event 00124 */ 00125 virtual void remove(bool fSynthetic) = 0; 00126 00127 // ----- QueryMap::Entry interface -------------------------- 00128 00129 public: 00130 /** 00131 * {@inheritDoc} 00132 */ 00133 virtual Object::Holder extract(ValueExtractor::View vExtractor) const = 0; 00134 00135 // ----- Map::Entry interface ------------------------------- 00136 00137 public: 00138 /** 00139 * Return the key corresponding to this entry. The resultant 00140 * key does not necessarily exist within the containing Map, 00141 * which is to say that calling <tt>containsKey(getKey())</tt> 00142 * on the containing Map could return false. To test for the 00143 * presence of this key within the Map, use {@link 00144 * #isPresent}, and to create the entry for the key, use 00145 * {@link #setValue}. 00146 * 00147 * @return the key corresponding to this entry; may be NULL if 00148 * the underlying Map supports NULL keys 00149 */ 00150 using Map::Entry::getKey; 00151 00152 /** 00153 * Return the value corresponding to this entry. If the entry 00154 * does not exist, then the value will be NULL. To 00155 * differentiate between a NULL value and a non-existent 00156 * entry, use {@link #isPresent}. 00157 * 00158 * <b>Note:</b> any modifications to the value retrieved using 00159 * this method are not guaranteed to persist unless followed 00160 * by a {@link #setValue} or {@link #update} call. 00161 * 00162 * @return the value corresponding to this entry; may be NULL 00163 * if the value is NULL or if the Entry does not exist 00164 * in the Map 00165 */ 00166 using Map::Entry::getValue; 00167 00168 /** 00169 * Store the value corresponding to this entry. If the entry 00170 * does not exist, then the entry will be created by invoking 00171 * this method, even with a NULL value (assuming the Map 00172 * supports NULL values). 00173 * 00174 * @param ohValue the new value for this Entry 00175 * 00176 * @return the previous value of this Entry, or NULL if the 00177 * Entry did not exist 00178 */ 00179 using Map::Entry::setValue; 00180 }; 00181 00182 00183 // ----- inner interface: EntryProcessor -------------------------------- 00184 00185 public: 00186 /** 00187 * An invocable agent that operates against the Entry objects within a 00188 * Map. 00189 */ 00190 class COH_EXPORT EntryProcessor 00191 : public interface_spec<EntryProcessor> 00192 { 00193 // ----- EntryProcessor interface --------------------------- 00194 00195 public: 00196 /** 00197 * Process a Map::Entry object. 00198 * 00199 * @param hEntry the Entry to process 00200 * 00201 * @return the result of the processing, if any 00202 */ 00203 virtual Object::Holder process( 00204 Entry::Handle hEntry) const = 0; 00205 00206 /** 00207 * Process a Set of InvocableMap::Entry objects. This method 00208 * is semantically equivalent to: 00209 * <pre> 00210 * Map::Handle hMapResults = HashMap::create(); 00211 * for (Iterator::Handle hIter = vSetEntries->iterator(); 00212 * iter->hasNext; ) 00213 * { 00214 * InvocableMap::Entry::Handle hEntry = 00215 * cast<InvocableMap::Entry::Handle>(hIter->next()); 00216 * hMapResults->put(hEntry->getKey(), process(hEntry)); 00217 * } 00218 * return hMapResults; 00219 * </pre> 00220 * 00221 * @param vSetEntries a Set of InvocableMap::Entry objects 00222 * to process 00223 * 00224 * @return a Map containing the results of the processing, up 00225 * to one entry for each InvocableMap::Entry that was 00226 * processed, keyed by the keys of the Map that were 00227 * processed, with a corresponding value being the 00228 * result of the processing for each key 00229 */ 00230 virtual Map::View processAll(Set::View vSetEntries) const = 0; 00231 }; 00232 00233 00234 // ----- inner interface: EntryAggregator ------------------------------- 00235 00236 public: 00237 /** 00238 * An EntryAggregator represents processing that can be directed to 00239 * occur against some subset of the entries in an InvocableMap, 00240 * resulting in a aggregated result. Common examples of aggregation 00241 * include functions such as min(), max() and avg(). However, the 00242 * concept of aggregation applies to any process that needs to 00243 * evaluate a group of entries to come up with a single answer. 00244 */ 00245 class COH_EXPORT EntryAggregator 00246 : public interface_spec<EntryAggregator> 00247 { 00248 // ----- EntryAggregator interface -------------------------- 00249 00250 public: 00251 /** 00252 * Process a set of InvocableMap::Entry objects in order to 00253 * produce an aggregated result. 00254 * 00255 * @param vSetEntries a Set of read-only InvocableMap::Entry 00256 * objects to aggregate 00257 * 00258 * @return the aggregated result from processing the entries 00259 */ 00260 virtual Object::Holder aggregate(Set::View vSetEntries) = 0; 00261 }; 00262 00263 00264 // ----- inner interface: ParallelAwareAggregator ----------------------- 00265 00266 public: 00267 /** 00268 * A ParallelAwareAggregator is an advanced extension to 00269 * EntryAggregator that is explicitly capable of being run in 00270 * parallel, for example in a distributed environment. 00271 */ 00272 class COH_EXPORT ParallelAwareAggregator 00273 : public interface_spec<ParallelAwareAggregator, 00274 implements<EntryAggregator> > 00275 { 00276 // ----- ParallelAwareAggregator interface ------------------ 00277 00278 public: 00279 /** 00280 * Get an aggregator that can take the place of this 00281 * aggregator in situations in which the InvocableMap can 00282 * aggregate in parallel. 00283 * 00284 * @return the aggregator that will be run in parallel 00285 */ 00286 virtual EntryAggregator::Handle getParallelAggregator() = 0; 00287 00288 /** 00289 * Aggregate the results of the parallel aggregations. 00290 * 00291 * @param vCollResults the parallel aggregation results 00292 * 00293 * @return the aggregation of the parallel aggregation results 00294 */ 00295 virtual Object::Holder aggregateResults( 00296 Collection::View vCollResults) = 0; 00297 }; 00298 00299 00300 // ----- InvocableMap interface ----------------------------------------- 00301 00302 public: 00303 /** 00304 * Invoke the passed EntryProcessor against the Entry specified by the 00305 * passed key, returning the result of the invocation. 00306 * 00307 * @param vKey the key to process; it is not required to exist 00308 * within the Map 00309 * @param hAgent the EntryProcessor to use to process the specified 00310 * key 00311 * 00312 * @return the result of the invocation as returned from the 00313 * EntryProcessor 00314 */ 00315 virtual Object::Holder invoke(Object::View vKey, 00316 EntryProcessor::Handle hAgent) = 0; 00317 00318 /** 00319 * Invoke the passed EntryProcessor against the entries specified by 00320 * the passed keys, returning the result of the invocation for each. 00321 * 00322 * @param vCollKeys the keys to process; these keys are not required 00323 * to exist within the Map 00324 * @param hAgent the EntryProcessor to use to process the 00325 * specified keys 00326 * 00327 * @return a Map containing the results of invoking the EntryProcessor 00328 * against each of the specified keys 00329 */ 00330 virtual Map::View invokeAll(Collection::View vCollKeys, 00331 EntryProcessor::Handle hAgent) = 0; 00332 00333 /** 00334 * Invoke the passed EntryProcessor against the set of entries that 00335 * are selected by the given Filter, returning the result of the 00336 * invocation for each. 00337 * 00338 * Unless specified otherwise, InvocableMap implementations will 00339 * perform this operation in two steps: (1) use the filter to retrieve 00340 * a matching entry set; (2) apply the agent to every filtered entry. 00341 * This algorithm assumes that the agent's processing does not affect 00342 * the result of the specified filter evaluation, since the filtering 00343 * and processing could be performed in parallel on different threads. 00344 * If this assumption does not hold, the processor logic has to be 00345 * idempotent, or at least re-evaluate the filter. This could be 00346 * easily accomplished by wrapping the processor with a 00347 * ConditionalProcessor. 00348 * 00349 * @param vFilter a Filter that results in the set of keys to be 00350 * processed 00351 * @param hAgent the EntryProcessor to use to process the specified 00352 * keys 00353 * 00354 * @return a Map containing the results of invoking the EntryProcessor 00355 * against the keys that are selected by the given Filter 00356 */ 00357 virtual Map::View invokeAll(Filter::View vFilter, 00358 EntryProcessor::Handle hAgent) = 0; 00359 00360 /** 00361 * Perform an aggregating operation against the entries specified by 00362 * the passed keys. 00363 * 00364 * @param vCollKeys the Collection of keys that specify the entries 00365 * within this Map to aggregate across 00366 * @param hAgent the EntryAggregator that is used to aggregate 00367 * across the specified entries of this Map 00368 * 00369 * @return the result of the aggregation 00370 */ 00371 virtual Object::Holder aggregate(Collection::View vCollKeys, 00372 EntryAggregator::Handle hAgent) const = 0; 00373 00374 /** 00375 * Perform an aggregating operation against the set of entries that 00376 * are selected by the given Filter. 00377 * 00378 * @param vFilter the Filter that is used to select entries within 00379 * this Map to aggregate across 00380 * @param hAgent the EntryAggregator that is used to aggregate 00381 * across the selected entries of this Map 00382 * 00383 * @return the result of the aggregation 00384 */ 00385 virtual Object::Holder aggregate(Filter::View vFilter, 00386 EntryAggregator::Handle hAgent) const = 0; 00387 }; 00388 00389 COH_CLOSE_NAMESPACE2 00390 00391 #endif // COH_INVOCABLE_MAP_HPP