1 /***
2 * AbstractProducer.java
3 *
4 * This file is part of the creme library.
5 * The creme library intends to ease the development effort of large
6 * applications by providing easy to use support classes.
7 *
8 * Copyright (C) 2002 Denis Bregeon
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * contact information: dbregeon@sourceforge.net
25 */
26 package org.jcreme.processing;
27
28 import java.util.ArrayList;
29 import java.util.Collection;
30
31 /***
32 * This class takes care of the basic production mechanisms. It is valid for any
33 * Producer since it does nor introduce any dependency on a Consumer. Producers
34 * should basically derive from this class although this is by no a necessity.
35 *
36 * @author $Author: dbregeon $
37 * @version $Revision: 1.2 $
38 */
39 public abstract class AbstractProducer implements Producer {
40 /***
41 * The items which have been produced.
42 */
43 private final ArrayList producedItems;
44
45 /***
46 * The items which are being consumed.
47 */
48 private final ArrayList itemsBeingConsumed;
49
50 /***
51 * Boolean flag that says whether the production is over.
52 */
53 private boolean productionIsOver = false;
54
55 /***
56 * Creates new AbstractProducer
57 *
58 * @param initialProductionQueueSize
59 * the size of the production queue when it is initialized.
60 * @param initialValidationQueueSize
61 * the size of the validation queue when it is initialized.
62 */
63 public AbstractProducer(int initialProductionQueueSize,
64 int initialValidationQueueSize) {
65 this.producedItems = new ArrayList(initialProductionQueueSize);
66 this.itemsBeingConsumed = new ArrayList(initialValidationQueueSize);
67 }
68
69 /***
70 * Returns the next item free for consumption. If no item is available, the
71 * call blocks until one is available.
72 *
73 * @return The next item free for consumption.
74 * @see Producer#nextItem
75 */
76 public Object nextItem() {
77 return nextItem(-1);
78 }
79
80 /***
81 * Returns the next item free for consumption. If no item is available, the
82 * call blocks until the timeout expires or an object is available.
83 *
84 * @param timeout
85 * the number of milliseconds the call will wait for an available
86 * item.
87 * @return The next item free for consumption.
88 * @see Producer#nextItem
89 */
90 public Object nextItem(final int timeout) {
91 Object tempItem = null;
92 boolean waitExpired = false;
93 try {
94 synchronized (this.producedItems) {
95 while ((!waitExpired) && (this.producedItems.isEmpty())
96 && (!this.productionIsOver)) {
97 if (timeout >= 0) {
98 this.producedItems.wait(timeout);
99 waitExpired = true;
100 } else {
101 this.producedItems.wait();
102 }
103 }
104 if (!this.producedItems.isEmpty()) {
105 tempItem = this.producedItems.get(0);
106 this.producedItems.remove(tempItem);
107 this.producedItems.notifyAll();
108 }
109 }
110 if (tempItem != null) {
111 synchronized (this.itemsBeingConsumed) {
112 this.itemsBeingConsumed.add(tempItem);
113 this.itemsBeingConsumed.notifyAll();
114 }
115 }
116 } catch (java.lang.InterruptedException e) {
117 e.printStackTrace();
118 } catch (java.util.NoSuchElementException e) {
119 e.printStackTrace();
120 }
121 return tempItem;
122 }
123
124 /***
125 * Validates an item, i.e. marks it as having been consumed. After a
126 * successfull call to this method, the item should be removed from the
127 * memory of the Producer. An unsuccessfull call to this method may call for
128 * a redo action.
129 *
130 * @param theItem
131 * The item to be validated.
132 * @return true is validation was successful.
133 * @see Producer#validateItem
134 */
135 public boolean validateItem(final Object theItem) {
136 boolean result = false;
137 if (theItem != null) {
138 synchronized (this.itemsBeingConsumed) {
139 result = this.itemsBeingConsumed.remove(theItem);
140 this.itemsBeingConsumed.notifyAll();
141 }
142 }
143 return result;
144 }
145
146 /***
147 * This method enables to put a newly produced item in the production queue.
148 * After a call to this method, it can be consumed by any consumer that uses
149 * this producer.
150 *
151 * @param theItem
152 * the item to make available for consumption.
153 */
154 protected void publishItem(final Object theItem) {
155 synchronized (this.producedItems) {
156 if (theItem != null) {
157 this.producedItems.add(theItem);
158 }
159 this.producedItems.notifyAll();
160 }
161 }
162
163 /***
164 * Sets a flag that shows whether the production is over.
165 *
166 * @param bool
167 * The boolean value that the flag has to be set on.
168 * @see Producer#setProductionOver
169 */
170 public void setProductionOver(final boolean bool) {
171 this.productionIsOver = bool;
172 synchronized (this.producedItems) {
173 this.producedItems.notifyAll();
174 }
175 }
176
177 /***
178 * Returns true if the production is over, false if not.
179 *
180 * @return True if the production is over, false if not.
181 * @see Producer#isProductionOver
182 */
183 public boolean isProductionOver() {
184 return this.productionIsOver;
185 }
186
187 /***
188 * Produces next item, i.e. marks it as consumable. This method does the
189 * actual "Production" work.
190 *
191 * @return True if there are still objects to produce, false otherwise.
192 */
193 public abstract boolean produceItem();
194
195 /***
196 * Returns the Collection of the items that are being consumed.
197 *
198 * @return The Collection of the items that are being consumed.
199 */
200 protected Collection getItemsBeingConsumed() {
201 return this.itemsBeingConsumed;
202 }
203
204 /***
205 * Returns the Collection of the items that are available for consumption.
206 *
207 * @return The Collection of the items that are available for consumption.
208 */
209 public Collection getProducedItems() {
210 return this.producedItems;
211 }
212 }