View Javadoc

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 }