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