001: /*
002: * <copyright>
003: *
004: * Copyright 2001-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.core.service;
028:
029: import java.util.Collection;
030:
031: import org.cougaar.core.blackboard.Subscriber;
032: import org.cougaar.core.blackboard.SubscriberException;
033: import org.cougaar.core.blackboard.Subscription;
034: import org.cougaar.core.blackboard.SubscriptionWatcher;
035: import org.cougaar.core.component.Service;
036: import org.cougaar.core.persist.Persistence;
037: import org.cougaar.core.persist.PersistenceNotEnabledException;
038: import org.cougaar.util.UnaryPredicate;
039:
040: /**
041: * This service provides transactional publish/subscribe access to
042: * the local agent's blackboard.
043: * <p>
044: * Most developers should extend {@link
045: * org.cougaar.core.plugin.ComponentPlugin} to handle threading and
046: * opening/closing transactions.
047: */
048: public interface BlackboardService extends Service {
049: //
050: //Subscriber/ Subscription stuff
051: //
052:
053: Subscriber getSubscriber();
054:
055: /**
056: * Request a subscription to all objects for which
057: * isMember.execute(object) is true. The returned Collection
058: * is a transactionally-safe set of these objects which is
059: * guaranteed not to change out from under you during run()
060: * execution.
061: *
062: * subscribe() may be called any time after
063: * load() completes.
064: */
065: Subscription subscribe(UnaryPredicate isMember);
066:
067: /**
068: * like subscribe(UnaryPredicate), but allows specification of
069: * some other type of Collection object as the internal representation
070: * of the collection.
071: * Alias for getSubscriber().subscribe(UnaryPredicate, Collection);
072: */
073: Subscription subscribe(UnaryPredicate isMember,
074: Collection realCollection);
075:
076: /**
077: * Alias for getSubscriber().subscribe(UnaryPredicate, boolean);
078: */
079: Subscription subscribe(UnaryPredicate isMember,
080: boolean isIncremental);
081:
082: /**
083: * Alias for <code>getSubscriber().subscribe(UnaryPredicate, Collection, boolean);</code>
084: * @param isMember a predicate to execute to ascertain
085: * membership in the collection of the subscription.
086: * @param realCollection a container to hold the contents of the subscription.
087: * @param isIncremental should be true if an incremental subscription is desired.
088: * An incremental subscription provides access to the incremental changes to the subscription.
089: * @return the Subsciption.
090: * @see org.cougaar.core.blackboard.Subscriber#subscribe
091: * @see org.cougaar.core.blackboard.Subscription
092: */
093: Subscription subscribe(UnaryPredicate isMember,
094: Collection realCollection, boolean isIncremental);
095:
096: /**
097: * Primary subscribe method, which registers a new subscription.
098: */
099: Subscription subscribe(Subscription subscription);
100:
101: /**
102: * Issue a query against the logplan. Similar in function to
103: * opening a new subscription, getting the results and immediately
104: * closing the subscription, but can be implemented much more efficiently.
105: * Note: the initial implementation actually does exactly this.
106: */
107: Collection query(UnaryPredicate isMember);
108:
109: /**
110: * Cancels the given Subscription which must have been returned by a
111: * previous invocation of subscribe(). Alias for
112: * <code> getSubscriber().unsubscribe(Subscription)</code>.
113: * @param subscription the subscription to cancel
114: * @see org.cougaar.core.blackboard.Subscriber#unsubscribe
115: */
116: void unsubscribe(Subscription subscription);
117:
118: int getSubscriptionCount();
119:
120: int getSubscriptionSize();
121:
122: int getPublishAddedCount();
123:
124: int getPublishChangedCount();
125:
126: int getPublishRemovedCount();
127:
128: /**
129: * @return true iff collection contents have changed since the last
130: * transaction.
131: */
132: boolean haveCollectionsChanged();
133:
134: //
135: // Blackboard changes publishing
136: //
137:
138: void publishAdd(Object o);
139:
140: void publishRemove(Object o);
141:
142: void publishChange(Object o);
143:
144: /**
145: * mark an element of the Plan as changed.
146: * Behavior is not defined if the object is not a member of the plan.
147: * There is no need to call this if the object was added or removed,
148: * only if the contents of the object itself has been changed.
149: * The changes parameter describes a set of changes made to the
150: * object beyond those tracked automatically by the object class
151: * (see the object class documentation for a description of which
152: * types of changes are tracked). Any additional changes are
153: * merged in <em>after</em> automatically collected reports.
154: * @param changes a set of ChangeReport instances or null.
155: */
156: void publishChange(Object o, Collection changes);
157:
158: //
159: // aliases for Transaction handling
160: //
161:
162: /**
163: * Open a transaction by grabbing the transaction lock and updating
164: * the subscriptions. This method blocks waiting for the
165: * transaction lock.
166: */
167: void openTransaction();
168:
169: /**
170: * Attempt to open a transaction by attempting to grab the
171: * transaction lock and updating the collections (iff we got the
172: * lock).
173: *
174: * This is equivalent to the old (misnamed) tryLockSubscriber method
175: * in PluginWrapper.
176: *
177: * @return true IFF a transaction was opened.
178: */
179: boolean tryOpenTransaction();
180:
181: /**
182: * Close a transaction opened by openTransaction() or a
183: * successful tryOpenTransaction(), flushing the change
184: * tracking (delta) lists of any open subscriptions.
185: * @exception SubscriberException IFF we did not own the transaction
186: * lock.
187: */
188: void closeTransaction() throws SubscriberException;
189:
190: /**
191: * Close a transaction opened by openTransaction() or a successful
192: * tryOpenTransaction(), but don't reset subscription changes or
193: * clear delta lists. In effect, defers changes tracked until next
194: * transaction.
195: * @exception SubscriberException IFF we did not own the transaction
196: * lock.
197: */
198: void closeTransactionDontReset();
199:
200: /**
201: * Close a transaction opened by openTransaction() or a
202: * successful tryOpenTransaction().
203: * @param resetp IFF true, all subscriptions will have
204: * their resetChanges() method called to clear any delta lists, etc.
205: * @exception SubscriberException IFF we did not own the transaction
206: * lock.
207: * @deprecated Use {@link #closeTransactionDontReset closeTransactionDontReset}
208: * This method becomes private after deprecation period expires.
209: */
210: void closeTransaction(boolean resetp) throws SubscriberException;
211:
212: /**
213: * Check to see if a transaction is open and owned by the current thread.
214: * There is no method to check to see if the subscribe has a transaction
215: * open which is owned by a different thread, since that would not be a safe
216: * operation.
217: * @return true IFF the current thread already has an open transaction.
218: * @note This method should really only be used in assertions and the like, since
219: * code should generally know exactly when it is or is not inside an open transaction.
220: */
221: boolean isTransactionOpen();
222:
223: //
224: // plugin hooks
225: //
226:
227: /**
228: * called when the client (Plugin) requests that it be waked again.
229: * by default, just calls wakeSubscriptionWatchers, but subclasses
230: * may be more circumspect.
231: */
232: void signalClientActivity();
233:
234: /** register a watcher of subscription activity */
235: SubscriptionWatcher registerInterest(SubscriptionWatcher w);
236:
237: /** register a watcher of subscription activity */
238: SubscriptionWatcher registerInterest();
239:
240: /** stop watching subscription activity */
241: void unregisterInterest(SubscriptionWatcher w)
242: throws SubscriberException;
243:
244: //
245: // persistence hooks
246: //
247:
248: /**
249: * indicate that this blackboard service information should (or should not)
250: * be persisted.
251: */
252: void setShouldBePersisted(boolean value);
253:
254: /** @return the current value of the persistence setting */
255: boolean shouldBePersisted();
256:
257: // /** indicate that the blackboard view is ready to persist */
258: // void setReadyToPersist();
259:
260: /**
261: * is this BlackboardService the result of a rehydration of a persistence
262: * snapshot?
263: */
264: boolean didRehydrate();
265:
266: /**
267: * Take a persistence snapshot now. If called from inside a
268: * transaction (the usual case for a plugin), the transaction will
269: * be closed and reopened. This means that a plugin must first
270: * process all of its existing envelopes before calling
271: * <code>persistNow()</code> and then process a potential new set of
272: * envelopes after re-opening the transaction. Otherwise, the
273: * changes will be lost.
274: * @exception PersistenceNotEnabledException
275: */
276: void persistNow() throws PersistenceNotEnabledException;
277:
278: /** Hook to allow access to Blackboard persistence mechanism */
279: Persistence getPersistence();
280:
281: /**
282: * BlackboardService.Delegate is an instantiable convenience class which may be
283: * used by Binder writers to bind BlackboardService, either as a simple
284: * protective indirection layer, or as the base class for more complex behavior.
285: * This implementation merely passes through all requests to a constructor
286: * specified delegate.
287: */
288: class Delegate implements BlackboardService {
289: private final BlackboardService bs;
290:
291: public Delegate(BlackboardService bs) {
292: this .bs = bs;
293: }
294:
295: public Subscriber getSubscriber() {
296: return bs.getSubscriber();
297: }
298:
299: public Subscription subscribe(UnaryPredicate isMember) {
300: return bs.subscribe(isMember);
301: }
302:
303: public Subscription subscribe(UnaryPredicate isMember,
304: Collection realCollection) {
305: return bs.subscribe(isMember, realCollection);
306: }
307:
308: public Subscription subscribe(UnaryPredicate isMember,
309: boolean isIncremental) {
310: return bs.subscribe(isMember, isIncremental);
311: }
312:
313: public Subscription subscribe(UnaryPredicate isMember,
314: Collection realCollection, boolean isIncremental) {
315: return bs
316: .subscribe(isMember, realCollection, isIncremental);
317: }
318:
319: public Subscription subscribe(Subscription subscription) {
320: return bs.subscribe(subscription);
321: }
322:
323: public Collection query(UnaryPredicate isMember) {
324: return bs.query(isMember);
325: }
326:
327: public void unsubscribe(Subscription subscription) {
328: bs.unsubscribe(subscription);
329: }
330:
331: public int getSubscriptionCount() {
332: return bs.getSubscriptionCount();
333: }
334:
335: public int getSubscriptionSize() {
336: return bs.getSubscriptionSize();
337: }
338:
339: public int getPublishAddedCount() {
340: return bs.getPublishAddedCount();
341: }
342:
343: public int getPublishChangedCount() {
344: return bs.getPublishChangedCount();
345: }
346:
347: public int getPublishRemovedCount() {
348: return bs.getPublishRemovedCount();
349: }
350:
351: public boolean haveCollectionsChanged() {
352: return bs.haveCollectionsChanged();
353: }
354:
355: public void publishAdd(Object o) {
356: bs.publishAdd(o);
357: }
358:
359: public void publishRemove(Object o) {
360: bs.publishRemove(o);
361: }
362:
363: public void publishChange(Object o) {
364: bs.publishChange(o);
365: }
366:
367: public void publishChange(Object o, Collection changes) {
368: bs.publishChange(o, changes);
369: }
370:
371: public void openTransaction() {
372: bs.openTransaction();
373: }
374:
375: public boolean tryOpenTransaction() {
376: return bs.tryOpenTransaction();
377: }
378:
379: public void closeTransaction() throws SubscriberException {
380: bs.closeTransaction();
381: }
382:
383: public void closeTransactionDontReset()
384: throws SubscriberException {
385: bs.closeTransactionDontReset();
386: }
387:
388: /**
389: * @deprecated Use {@link #closeTransactionDontReset closeTransactionDontReset}
390: */
391: public void closeTransaction(boolean resetp)
392: throws SubscriberException {
393: bs.closeTransaction(resetp);
394: }
395:
396: public boolean isTransactionOpen() {
397: return bs.isTransactionOpen();
398: }
399:
400: public void signalClientActivity() {
401: bs.signalClientActivity();
402: }
403:
404: public SubscriptionWatcher registerInterest(
405: SubscriptionWatcher w) {
406: return bs.registerInterest(w);
407: }
408:
409: public SubscriptionWatcher registerInterest() {
410: return bs.registerInterest();
411: }
412:
413: public void unregisterInterest(SubscriptionWatcher w)
414: throws SubscriberException {
415: bs.unregisterInterest(w);
416: }
417:
418: public void setShouldBePersisted(boolean value) {
419: bs.setShouldBePersisted(value);
420: }
421:
422: public boolean shouldBePersisted() {
423: return bs.shouldBePersisted();
424: }
425:
426: public void persistNow()
427: throws org.cougaar.core.persist.PersistenceNotEnabledException {
428: bs.persistNow();
429: }
430:
431: public boolean didRehydrate() {
432: return bs.didRehydrate();
433: }
434:
435: public Persistence getPersistence() {
436: return bs.getPersistence();
437: }
438: }
439: }
|