00001 /* 00002 * InvocableMap.hpp 00003 * 00004 * Copyright (c) 2000, 2020, 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 // ----- inner interface: PartialResultAggregator --------------- 00299 00300 public: 00301 /** 00302 * PartialResultAggregator allows for the intermediate {@link 00303 * #aggregatePartialResults aggregation} of the partial results of a {@link 00304 * ParallelAwareAggregator parallel aggregation}. 00305 */ 00306 class COH_EXPORT PartialResultAggregator 00307 : public interface_spec<PartialResultAggregator> 00308 { 00309 // ----- PartialResultAggregator interface -------------- 00310 00311 public: 00312 /** 00313 * Aggregate the results of the parallel aggregations, producing a 00314 * partial result logically representing the partial aggregation. The 00315 * returned partial result will be further {@link 00316 * ParallelAwareAggregator#aggregateResults aggregated} to produce 00317 * the final result. 00318 * 00319 * @param vColPartialResults the partial results 00320 * 00321 * @return an aggregation of the collection of partial results 00322 */ 00323 virtual Object::Holder aggregatePartialResults( 00324 Collection::View vColPartialResults) = 0; 00325 00326 }; 00327 }; 00328 00329 00330 // ----- InvocableMap interface ----------------------------------------- 00331 00332 public: 00333 /** 00334 * Invoke the passed EntryProcessor against the Entry specified by the 00335 * passed key, returning the result of the invocation. 00336 * 00337 * @param vKey the key to process; it is not required to exist 00338 * within the Map 00339 * @param hAgent the EntryProcessor to use to process the specified 00340 * key 00341 * 00342 * @return the result of the invocation as returned from the 00343 * EntryProcessor 00344 */ 00345 virtual Object::Holder invoke(Object::View vKey, 00346 EntryProcessor::Handle hAgent) = 0; 00347 00348 /** 00349 * Invoke the passed EntryProcessor against the entries specified by 00350 * the passed keys, returning the result of the invocation for each. 00351 * 00352 * @param vCollKeys the keys to process; these keys are not required 00353 * to exist within the Map 00354 * @param hAgent the EntryProcessor to use to process the 00355 * specified keys 00356 * 00357 * @return a Map containing the results of invoking the EntryProcessor 00358 * against each of the specified keys 00359 */ 00360 virtual Map::View invokeAll(Collection::View vCollKeys, 00361 EntryProcessor::Handle hAgent) = 0; 00362 00363 /** 00364 * Invoke the passed EntryProcessor against the set of entries that 00365 * are selected by the given Filter, returning the result of the 00366 * invocation for each. 00367 * 00368 * Unless specified otherwise, InvocableMap implementations will 00369 * perform this operation in two steps: (1) use the filter to retrieve 00370 * a matching entry set; (2) apply the agent to every filtered entry. 00371 * This algorithm assumes that the agent's processing does not affect 00372 * the result of the specified filter evaluation, since the filtering 00373 * and processing could be performed in parallel on different threads. 00374 * If this assumption does not hold, the processor logic has to be 00375 * idempotent, or at least re-evaluate the filter. This could be 00376 * easily accomplished by wrapping the processor with a 00377 * ConditionalProcessor. 00378 * 00379 * @param vFilter a Filter that results in the set of keys to be 00380 * processed 00381 * @param hAgent the EntryProcessor to use to process the specified 00382 * keys 00383 * 00384 * @return a Map containing the results of invoking the EntryProcessor 00385 * against the keys that are selected by the given Filter 00386 */ 00387 virtual Map::View invokeAll(Filter::View vFilter, 00388 EntryProcessor::Handle hAgent) = 0; 00389 00390 /** 00391 * Perform an aggregating operation against the entries specified by 00392 * the passed keys. 00393 * 00394 * @param vCollKeys the Collection of keys that specify the entries 00395 * within this Map to aggregate across 00396 * @param hAgent the EntryAggregator that is used to aggregate 00397 * across the specified entries of this Map 00398 * 00399 * @return the result of the aggregation 00400 */ 00401 virtual Object::Holder aggregate(Collection::View vCollKeys, 00402 EntryAggregator::Handle hAgent) const = 0; 00403 00404 /** 00405 * Perform an aggregating operation against the set of entries that 00406 * are selected by the given Filter. 00407 * 00408 * @param vFilter the Filter that is used to select entries within 00409 * this Map to aggregate across 00410 * @param hAgent the EntryAggregator that is used to aggregate 00411 * across the selected entries of this Map 00412 * 00413 * @return the result of the aggregation 00414 */ 00415 virtual Object::Holder aggregate(Filter::View vFilter, 00416 EntryAggregator::Handle hAgent) const = 0; 00417 00418 /** 00419 * Get the value associated with the given key or return the default value if 00420 * there is no value associated with the key. 00421 * 00422 * @param vKey the key 00423 * @param ohDefaultValue the default value 00424 * 00425 * @return the value to which the specified key is mapped, 00426 * or defaultValue if this map contains no mapping for the key 00427 * 00428 * @since Coherence 12.2.1 00429 */ 00430 virtual Object::Holder getOrDefault(Object::View vKey, 00431 Object::Holder ohDefaultValue) const; 00432 00433 /** 00434 * If the specified key is not already associated with a value (or is 00435 * mapped to null) associates it with the given value and returns null, 00436 * else returns the current value. 00437 * 00438 * @param vKey the key 00439 * @param vValue the value 00440 * 00441 * @return the previous value associated with the specified key, 00442 * or null if there was no mapping for the key. 00443 * 00444 * @since Coherence 12.2.1 00445 */ 00446 virtual Object::Holder putIfAbsent(Object::View vKey, 00447 Object::Holder ohValue); 00448 00449 /** 00450 * Removes the entry for the specified key only if it is currently 00451 * mapped to the specified value. 00452 * 00453 * @param vKey the key 00454 * @param vValue the value 00455 * 00456 * @return true if the value was removed 00457 * 00458 * @since Coherence 12.2.1 00459 */ 00460 virtual bool removeValue(Object::View vKey, 00461 Object::View vValue); 00462 00463 /** 00464 * Replaces the entry for the specified key only if it is currently 00465 * mapped to some value. 00466 * 00467 * @param vKey the key 00468 * @param vValue the value 00469 * 00470 * @return the previous value associated with the specified key, 00471 * or null if there was no mapping for the key. A null return 00472 * can also indicate that the map previously associated null 00473 * with the key. 00474 * 00475 * @since Coherence 12.2.1 00476 */ 00477 virtual Object::Holder replace(Object::View vKey, 00478 Object::Holder ohValue); 00479 00480 /** 00481 * Replaces the entry for the specified key only if currently mapped 00482 * to the specified value. 00483 * 00484 * @param vKey the key 00485 * @param vOldValue the old value 00486 * @param vNewValue the new value 00487 * 00488 * @return true if the value was replaced 00489 * 00490 * @since Coherence 12.2.1 00491 */ 00492 virtual bool replace(Object::View vKey, 00493 Object::View vOldValue, Object::Holder ohNewValue); 00494 }; 00495 00496 COH_CLOSE_NAMESPACE2 00497 00498 #endif // COH_INVOCABLE_MAP_HPP