001: package com.jamonapi.utils;
002:
003: import java.util.*;
004:
005: /** <p>This object can contain a configurable number of items in a buffer. The items kept are rows in a 2 dim
006: * array and so the data can be viewed in a table. It is used in jamon to store recent exceptions, and
007: * sql queries from the various proxy classes. However it may be used elsewhere. It is thread safe.
008: * By default the buffer holds 50 elements, but this can be overridden in the constructor.</P
009: *
010: * <p>It uses a bufferHolder to determine whether a value should be added and another one removed when the buffer is full. For example
011: * the value could only be added if the new value is greater than the smallest member of the BufferList. Simply implement the BufferHolder
012: * interface to implement your desired rules.
013: * </p>
014: * @author steve souza
015: *
016: */
017:
018: public class BufferList implements DetailData {
019:
020: private boolean enabled = true;
021: private int bufferSize = 50;
022: private String[] header;
023: private BufferHolder bufferHolder;
024:
025: /** Constructor that takes the header of the structure of the rows that are stored.
026: * For example header could be {"Time", "Exception info",};
027: * Uses a FIFOBuffer.
028: * @param header
029: */
030:
031: public BufferList(String[] header) {
032: this .header = header;
033: this .bufferHolder = new FIFOBufferHolder();
034: }
035:
036: /** Pass in the header and bufferHolder to be used */
037: public BufferList(String[] header, BufferHolder bufferHolder) {
038: this .header = header;
039: this .bufferHolder = bufferHolder;
040: }
041:
042: /** Use a FIFOBuffer and specify its header and size */
043: public BufferList(String[] header, int bufferSize) {
044: this .header = header;
045: this .bufferSize = bufferSize;
046: this .bufferHolder = new FIFOBufferHolder();
047: }
048:
049: /** Specify the header, bufferSize and BufferHolder to be used in the BufferList */
050: public BufferList(String[] header, int bufferSize,
051: BufferHolder bufferHolder) {
052: this .header = header;
053: this .bufferSize = bufferSize;
054: this .bufferHolder = bufferHolder;
055: }
056:
057: private BufferList(String[] header, int bufferSize,
058: boolean enabled, BufferHolder bufferHolder) {
059: this .header = header;
060: this .bufferSize = bufferSize;
061: this .enabled = enabled;
062: this .bufferHolder = bufferHolder;
063: }
064:
065: /**
066: * Get the number of Exceptions that can be stored in the buffer before the oldest entries must
067: * be removed.
068: *
069: */
070: public synchronized int getBufferSize() {
071: return bufferSize;
072: }
073:
074: public synchronized void setBufferHolder(BufferHolder bufferHolder) {
075: this .bufferHolder = bufferHolder;
076: }
077:
078: /**
079: * Set the number of Exceptions that can be stored in the buffer before the oldest entries must
080: * be removed. A value of 0 will disable the collection of Exceptions in the buffer. Note if
081: * MonProxy is disabled exceptions will also not be put in the buffer.
082: *
083: */
084:
085: public synchronized void setBufferSize(int newBufferSize) {
086:
087: if (bufferSize > newBufferSize)
088: resetBuffer(reduceBuffer(newBufferSize));
089:
090: bufferSize = newBufferSize;
091:
092: }
093:
094: /** Reduce size of buffer while not losing current elements beyond what the size reduction would cause. If the size is increased then no loss
095: * of data occurs.
096: * */
097: private LinkedList reduceBuffer(int newSize) {
098: LinkedList newBuffer = new LinkedList();
099: List original = bufferHolder.getOrderedCollection();
100: Collections.reverse(original);// reverse to save the most recent values
101: Iterator iter = original.iterator();
102: int i = 0;
103: while (iter.hasNext() && i < newSize) {
104: newBuffer.add(iter.next());
105: i++;
106: }
107:
108: return newBuffer;
109: }
110:
111: /**
112: * Remove all Exceptions from the buffer. Not sure why this was needed vs reset()
113: *
114: */
115: public synchronized void resetBuffer() {
116: reset();
117: }
118:
119: private void resetBuffer(LinkedList list) {
120: bufferHolder.setCollection(list);
121:
122: }
123:
124: /** Return true if the bufferList is empty */
125: public boolean isEmpty() {
126: return getRowCount() == 0;
127: }
128:
129: /** Return true if the bufferList has data */
130: public boolean hasData() {
131: return !isEmpty();
132: }
133:
134: /** Return the rows in the BufferList */
135: public int getRowCount() {
136: return (bufferHolder == null) ? 0 : bufferHolder
137: .getCollection().size();
138: }
139:
140: /** Return the underlying Collection that holds the BufferList */
141: public List getCollection() {
142: return bufferHolder.getCollection();
143: }
144:
145: /** Returns true if MonProxy is enabled. */
146: public synchronized boolean isEnabled() {
147: return enabled;
148: }
149:
150: /** Enable monitoring */
151: public synchronized void enable() {
152: enabled = true;
153: }
154:
155: /** Disable monitoring */
156: public synchronized void disable() {
157: enabled = false;
158: }
159:
160: /** Reset BufferList. It will empty the buffer and leave its size at the current value */
161: public synchronized void reset() {
162: bufferHolder.setCollection(new LinkedList());
163: }
164:
165: /** Get the header that can be used to display the buffer. Use getDetailData() method instead.
166: *
167: * */
168: public String[] getHeader() {
169: return header;
170: }
171:
172: /** Get the buffer as an array, so it can be displayed. Use getDetailData() method instead.
173: * @deprecated */
174: public Object[][] getData() {
175: return new BufferListDetailData(this ).getData();
176: }
177:
178: public DetailData getDetailData() {
179: return new BufferListDetailData(this );
180: }
181:
182: /** Add a row to be held in the buffer. If the buffer is full the oldest one will be removed. */
183: public synchronized void addRow(Object[] row) {
184: addRow((Object) row);
185: }
186:
187: public synchronized void addRow(Object obj) {
188: if (!enabled || bufferSize <= 0)
189: return;
190:
191: // remove the oldest element if the buffer is to capacity.
192: if (getRowCount() >= bufferSize
193: && bufferHolder.shouldReplaceWith(obj)) {
194: bufferHolder.remove(obj);
195: }
196:
197: if (getRowCount() < bufferSize) {
198: bufferHolder.add(obj);
199: }
200:
201: }
202:
203: public synchronized BufferList copy() {
204: return new BufferList(header, bufferSize, enabled, bufferHolder
205: .copy());
206: }
207:
208: public static void main(String[] args) {
209: BufferList bl = new BufferList(
210: new String[] { "fname", "mname" });
211: Object[][] data = { { "steven", "thomas", "souza" },
212: { "mindy", "darci", "bobish" } };
213: bl.addRow(data[0]);
214: bl.addRow(data[1]);
215: DetailData detailData = bl.getDetailData();
216: String[] h = detailData.getHeader();
217: System.out.println("1) header1");
218: for (int i = 0; i < h.length; i++)
219: System.out.println(h[i]);
220:
221: System.out.println("2) data1");
222: Misc.disp(detailData.getData());
223:
224: bl = new BufferList(new String[] { "fname", "mname", "lname",
225: "salary" });
226: bl.addRow(data[0]);
227: bl.addRow(data[1]);
228:
229: detailData = bl.getDetailData();
230: h = detailData.getHeader();
231: System.out.println("3) header2");
232: for (int i = 0; i < h.length; i++)
233: System.out.println(h[i]);
234:
235: System.out.println("3) data1");
236: Misc.disp(detailData.getData());
237: }
238:
239: }
|