001: /*
002: * Bossa Workflow System
003: *
004: * $Id: Resource.java,v 1.15 2004/01/29 21:24:37 gdvieira Exp $
005: *
006: * Copyright (C) 2003,2004 OpenBR Sistemas S/C Ltda.
007: *
008: * This file is part of Bossa.
009: *
010: * Bossa is free software; you can redistribute it and/or modify it
011: * under the terms of version 2 of the GNU General Public License as
012: * published by the Free Software Foundation.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public
020: * License along with this program; if not, write to the
021: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
022: * Boston, MA 02111-1307, USA.
023: */
024:
025: package com.bigbross.bossa.resource;
026:
027: import java.io.Serializable;
028: import java.util.Collections;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.Set;
032:
033: import com.bigbross.bossa.Bossa;
034: import com.bigbross.bossa.BossaException;
035:
036: /**
037: * This class represents a single resource or a group of resources.
038: * A group of resources may include or exclude other resources. <p>
039: *
040: * @author <a href="http://www.bigbross.com">BigBross Team</a>
041: */
042: public class Resource implements Container, Serializable {
043:
044: private ResourceRegistry resourceRegistry;
045:
046: private String id;
047:
048: private Set includes = new HashSet();
049:
050: private Set excludes = new HashSet();
051:
052: /**
053: * Creates a new <code>Resource</code> instance with the given
054: * identifier. <p>
055: *
056: * @param resourceRegistry the resource registry this resource is
057: * registered into.
058: * @param id the resource id.
059: */
060: Resource(ResourceRegistry resourceRegistry, String id) {
061: this .resourceRegistry = resourceRegistry;
062: this .id = id;
063: }
064:
065: /**
066: * Returns the resource registry this resource is registered into. <p>
067: *
068: * @return the resource registry this resource is registered into.
069: */
070: ResourceRegistry getResourceRegistry() {
071: return resourceRegistry;
072: }
073:
074: /**
075: * Returns the bossa engine this resource is part, if any. <p>
076: *
077: * @return the bossa engine this resource is part,
078: * <code>null</code> if not part of a bossa engine.
079: */
080: Bossa getBossa() {
081: if (getResourceRegistry() != null) {
082: return getResourceRegistry().getBossa();
083: } else {
084: return null;
085: }
086: }
087:
088: /**
089: * Returns the resource identifier. <p>
090: *
091: * @return the resource id.
092: */
093: public String getId() {
094: return id;
095: }
096:
097: /**
098: * Returns <code>true</code> if this resource includes any other
099: * resources, so it is a group.
100: *
101: * @return <code>true</code> if it is a group,
102: * <code>false</code> otherwise.
103: */
104: public boolean isGroup() {
105: return includes.size() > 0;
106: }
107:
108: /**
109: * Returns the includes list of this resource. <p>
110: *
111: * @return the includes list of this resource.
112: */
113: public Set getIncludes() {
114: return Collections.unmodifiableSet(includes);
115: }
116:
117: /**
118: * Returns the excludes list of this resource. <p>
119: *
120: * @return the excludes list of this resource.
121: */
122: public Set getExcludes() {
123: return Collections.unmodifiableSet(excludes);
124: }
125:
126: /**
127: * Includes a resource in this resource. Removes the resource from
128: * the excludes list if needed. <p>
129: *
130: * @param resource the resource to be included.
131: * @return <code>false</code> if resource includes this resource,
132: * <code>true</code> otherwise.
133: * @exception PersistenceException if an error occours when making the
134: * execution of this method persistent.
135: */
136: public boolean include(Resource resource) throws BossaException {
137: ResourceTransaction includeTransaction = new IncludeInResource(
138: this , resource);
139: return ((Boolean) getBossa().execute(includeTransaction))
140: .booleanValue();
141: }
142:
143: /**
144: * Includes a resource in this resource. Removes the resource from
145: * the excludes list if needed. <p>
146: *
147: * This method does not create a transaction in the prevalent system. The
148: * execution of this method will not be persistent unless it is called
149: * inside an appropriate transaction. <p>
150: *
151: * @param resource the resource to be included.
152: * @param notify if this operation should be notified.
153: * @return <code>false</code> if resource includes this resource,
154: * <code>true</code> otherwise.
155: */
156: public boolean includeImpl(Resource resource, boolean notify) {
157: if (resource.depends(this )) {
158: return false;
159: }
160: excludes.remove(resource);
161: includes.add(resource);
162: if (notify) {
163: ResourceEvents queue = new ResourceEvents();
164: queue.newTwoResourcesEvent(getBossa(),
165: ResourceEvents.ID_INCLUDE_IN_RESOURCE, resource,
166: this );
167: queue.notifyAll(getBossa());
168: }
169: return true;
170: }
171:
172: /**
173: * Excludes a resource from this resource. Removes the resource from
174: * the includes list if needed. <p>
175: *
176: * @param resource the resource to be excluded.
177: * @return <code>false</code> if resource excludes this resource,
178: * <code>true</code> otherwise.
179: * @exception PersistenceException if an error occours when making the
180: * execution of this method persistent.
181: */
182: public boolean exclude(Resource resource) throws BossaException {
183: ResourceTransaction excludeTransaction = new ExcludeInResource(
184: this , resource);
185: return ((Boolean) getBossa().execute(excludeTransaction))
186: .booleanValue();
187: }
188:
189: /**
190: * Excludes a resource from this resource. Removes the resource from
191: * the includes list if needed. <p>
192: *
193: * This method does not create a transaction in the prevalent system. The
194: * execution of this method will not be persistent unless it is called
195: * inside an appropriate transaction. <p>
196: *
197: * @param resource the resource to be excluded.
198: * @param notify if this operation should be notified.
199: * @return <code>false</code> if resource excludes this resource,
200: * <code>true</code> otherwise.
201: */
202: public boolean excludeImpl(Resource resource, boolean notify) {
203: if (resource.depends(this )) {
204: return false;
205: }
206: includes.remove(resource);
207: excludes.add(resource);
208: if (notify) {
209: ResourceEvents queue = new ResourceEvents();
210: queue.newTwoResourcesEvent(getBossa(),
211: ResourceEvents.ID_EXCLUDE_IN_RESOURCE, resource,
212: this );
213: queue.notifyAll(getBossa());
214: }
215: return true;
216: }
217:
218: /**
219: * Removes a resource from this resource. Effectively removes it from
220: * any of the includes or excludes list. <p>
221: *
222: * @param resource the resource to be removed.
223: * @exception PersistenceException if an error occours when making the
224: * execution of this method persistent.
225: */
226: public void remove(Resource resource) throws BossaException {
227: ResourceTransaction removeTransaction = new RemoveFromResource(
228: this , resource);
229: getBossa().execute(removeTransaction);
230: }
231:
232: /**
233: * Removes a resource from this resource. Effectively removes it from
234: * any of the includes or excludes list. <p>
235: *
236: * This method does not create a transaction in the prevalent system. The
237: * execution of this method will not be persistent unless it is called
238: * inside an appropriate transaction. <p>
239: *
240: * @param resource the resource to be removed.
241: * @param notify if this operation should be notified.
242: */
243: public void removeImpl(Resource resource, boolean notify) {
244: boolean inc = includes.remove(resource);
245: boolean exc = excludes.remove(resource);
246: if ((inc || exc) && notify) {
247: ResourceEvents queue = new ResourceEvents();
248: queue.newTwoResourcesEvent(getBossa(),
249: ResourceEvents.ID_REMOVE_FROM_RESOURCE, resource,
250: this );
251: queue.notifyAll(getBossa());
252: }
253: }
254:
255: /**
256: * Determines if a resource is contained in this resource. <p>
257: *
258: * @param resource the resource to be looked for.
259: * @return <code>true</code> if the resource is found,
260: * <code>false</code> otherwise.
261: */
262: public boolean contains(Resource resource) {
263:
264: if (this .equals(resource)) {
265: return true;
266: }
267:
268: if (!isGroup()) {
269: return false;
270: }
271:
272: if (excludes.contains(resource)) {
273: return false;
274: }
275:
276: Iterator it = excludes.iterator();
277: while (it.hasNext()) {
278: Resource curr = (Resource) it.next();
279: if (curr.contains(resource)) {
280: return false;
281: }
282: }
283:
284: if (includes.contains(resource)) {
285: return true;
286: }
287:
288: it = includes.iterator();
289: while (it.hasNext()) {
290: Resource curr = (Resource) it.next();
291: if (curr.contains(resource)) {
292: return true;
293: }
294: }
295:
296: return false;
297: }
298:
299: /**
300: * Checks if this resource depends on the given resource.
301: * Specifically, checks if it is necessary to call
302: * <code>contains()</code> in the given resource to check
303: * <code>contains()</code> in this resource. <p>
304: *
305: * @param resource the resource to be checked.
306: * @return <code>true</code> if this resource depends,
307: * <code>false</code> otherwise.
308: */
309: private boolean depends(Resource resource) {
310:
311: if (this .equals(resource)) {
312: return true;
313: }
314:
315: if (includes.contains(resource)) {
316: return true;
317: }
318:
319: Iterator it = includes.iterator();
320: while (it.hasNext()) {
321: Resource curr = (Resource) it.next();
322: if (curr.depends(resource)) {
323: return true;
324: }
325: }
326:
327: if (excludes.contains(resource)) {
328: return true;
329: }
330:
331: it = excludes.iterator();
332: while (it.hasNext()) {
333: Resource curr = (Resource) it.next();
334: if (curr.depends(resource)) {
335: return true;
336: }
337: }
338:
339: return false;
340: }
341:
342: /**
343: * Returns a string with the resource identifier. <p>
344: *
345: * @return a string representation of this resource.
346: */
347: public String toString() {
348: return id;
349: }
350:
351: }
|