001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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.mlm.plugin.ldm;
028:
029: import java.sql.ResultSet;
030: import java.sql.SQLException;
031: import java.sql.Statement;
032: import java.text.SimpleDateFormat;
033: import java.util.Collection;
034: import java.util.Date;
035: import java.util.Iterator;
036:
037: import org.cougaar.glm.ldm.oplan.OrgActivity;
038: import org.cougaar.glm.ldm.oplan.TimeSpan;
039: import org.cougaar.util.DBProperties;
040: import org.cougaar.util.TimeSpanSet;
041:
042: /** Reads OrgActivity for specified Oplan from a database table. Assumes it's
043: * being invoked on behalf of SQLOplanPlugin. Updates orgactivities maintained
044: * by SQLOplanPlugin.
045: */
046:
047: public class NewOrgActivityQueryHandler extends NewQueryHandler {
048: public static final String ACTIVITY_PARAMETER = "activity";
049: public static final String OPTEMPO_PARAMETER = "opTempo";
050: public static final String LOCATION_PARAMETER = "location";
051: public static final String OPCON_PARAMETER = "opCon";
052:
053: protected static final String QUERY_NAME = "OrgActivityQuery";
054:
055: protected static final int ATTRIBUTE_NAME = 1;
056: protected static final int ORG_ID = 2;
057: protected static final int ATTRIBUTE_VALUE = 3;
058: protected static final int START_HOUR = 4;
059: protected static final int END_HOUR = 5;
060: protected static final int STAGE_NUM = 6;
061:
062: protected static final int ACTIVITY_INDEX = 0;
063: protected static final int LOCATION_INDEX = 1;
064: protected static final int OPTEMPO_INDEX = 2;
065: protected static final int OPCON_INDEX = 3;
066:
067: protected String myActivityKey;
068: protected String myOpTempoKey;
069: protected String myLocationKey;
070: protected String myOpConKey;
071:
072: public NewOrgActivityQueryHandler(DBProperties adbp,
073: NewOplanPlugin plugin) throws SQLException {
074: super (adbp, plugin);
075: myActivityKey = dbp.getProperty(ACTIVITY_PARAMETER);
076: myOpTempoKey = dbp.getProperty(OPTEMPO_PARAMETER);
077: myLocationKey = dbp.getProperty(LOCATION_PARAMETER);
078: myOpConKey = dbp.getProperty(OPCON_PARAMETER);
079: }
080:
081: public Collection executeQueries(Statement statement)
082: throws SQLException {
083: String query = dbp.getQuery(QUERY_NAME, dbp);
084: String orgId = null;
085: ResultSet rs = statement.executeQuery(query);
086: TimeSpanSet opTempoSchedule = new TimeSpanSet();
087: TimeSpanSet activitySchedule = new TimeSpanSet();
088: TimeSpanSet locationSchedule = new TimeSpanSet();
089: TimeSpanSet opConSchedule = new TimeSpanSet();
090: TimeSpanSet schedule;
091: boolean haveOpCon = false;
092: while (rs.next()) {
093: String attribute_name = getString(rs, ATTRIBUTE_NAME);
094: String attribute_value = getString(rs, ATTRIBUTE_VALUE);
095: if (orgId == null)
096: orgId = getString(rs, ORG_ID);
097: if (attribute_name.equals(myOpTempoKey)) {
098: schedule = opTempoSchedule;
099: if (!attribute_value.equals(OrgActivity.HIGH_OPTEMPO)
100: && !attribute_value
101: .equals(OrgActivity.MEDIUM_OPTEMPO)
102: && !attribute_value
103: .equals(OrgActivity.LOW_OPTEMPO)) {
104: throw new SQLException("Unrecognized op tempo "
105: + attribute_value);
106: }
107: } else if (attribute_name.equals(myActivityKey)) {
108: schedule = activitySchedule;
109: } else if (attribute_name.equals(myLocationKey)) {
110: schedule = locationSchedule;
111: } else if (attribute_name.equals(myOpConKey)) {
112: haveOpCon = true;
113: schedule = opConSchedule;
114: } else {
115: if (logger.isErrorEnabled()) {
116: logger
117: .error("NewOrgActivityQueryHandler.processRow(): unexpected text in ATTRIBUTE_NAME column - "
118: + attribute_name);
119: }
120: continue;
121: }
122: OrgInfoElement element = new OrgInfoElement(
123: attribute_value, plugin.getCDay().getTime(),
124: (long) rs.getDouble(START_HOUR), (long) rs
125: .getDouble(END_HOUR));
126: if (schedule.intersectingSet(element).isEmpty()) {
127: if (logger.isDebugEnabled()) {
128: logger.debug("NewOrgActivityQueryHandler: Adding "
129: + element);
130: }
131: schedule.add(element);
132: } else {
133: if (logger.isErrorEnabled()) {
134: logger
135: .error("NewOrgActivityQueryHandler: found more than one "
136: + attribute_value
137: + " during "
138: + formatDate(element.getStartTime())
139: + " - "
140: + formatDate(element.getEndTime()));
141: }
142: }
143: }
144: //now each schedule has the set of values for each timespan for a given part of the OA
145:
146: TimeSpanSet timeSpanSet = new TimeSpanSet();
147:
148: //opConSchedule might be empty
149: OrgInfoElements[] oiElements = {
150: new OrgInfoElements(activitySchedule, "activity"),
151: new OrgInfoElements(locationSchedule, "location"),
152: new OrgInfoElements(opTempoSchedule, "opTempo"),
153: new OrgInfoElements(opConSchedule, "opCon") };
154:
155: long minStart = TimeSpan.MIN_VALUE;
156: while (true) {
157: long start = minStart;
158: long end = TimeSpan.MAX_VALUE;
159: int missing = 0;
160: int present = 0;
161: // Step all iterators/elements
162: // Need to pull out the values from each type of OA element for each necessary timespan
163: for (int i = 0; i < oiElements.length; i++) {
164: OrgInfoElement element = oiElements[i]
165: .endsAfter(minStart);
166: if (element == null) {
167: missing++;
168: if (logger.isDebugEnabled()) {
169: logger.debug("NOAQH: missing = " + missing
170: + " and haveOpCon value is: "
171: + haveOpCon);
172: }
173: } else {
174: present++;
175: if (logger.isDebugEnabled()) {
176: logger.debug("NOAQH: Element is: " + element);
177: logger.debug("NOAQH: present = " + present);
178: }
179: end = Math.min(end, element.getEndTime());
180: start = Math.max(start, element.getStartTime());
181: if (logger.isDebugEnabled()) {
182: logger.debug("end value is " + new Date(end));
183: logger.debug("start value is "
184: + new Date(start));
185: }
186: }
187: }
188:
189: if (missing > 1) {
190: //if the missing element is the OPCON its OK
191: return timeSpanSet;
192: }
193:
194: // if (missing > 0 ) {
195: // if (logger.isWarnEnabled() && present > 0) {
196: // StringBuffer msg = new StringBuffer();
197: // msg.append("NewOrgActivityQueryHandler: missing ");
198: // boolean first = true;
199: // for (int i = 0; i < oiElements.length; i++) {
200: // if (oiElements[i].isFinished()) {
201: // if (first) {
202: // first = false;
203: // } else {
204: // msg.append(", ");
205: // }
206: // msg.append(oiElements[i].getType());
207: // }
208: // }
209: // msg.append(" between ")
210: // .append(formatDate(start))
211: // .append(" - ")
212: // .append(formatDate(end));
213: // logger.warn(msg.toString());
214: // }
215: // return timeSpanSet;
216: // }
217:
218: if (start > minStart && minStart > TimeSpan.MIN_VALUE) {
219: if (logger.isInfoEnabled()) {
220: logger
221: .info("NewOrgActivityQueryHandler: schedule gap between "
222: + formatDate(minStart)
223: + " - "
224: + formatDate(start));
225: }
226: }
227:
228: String myOpCon = null;
229: if (haveOpCon) {
230: myOpCon = oiElements[OPCON_INDEX].getStringObject();
231: }
232: OrgActivity orgActivity = plugin.makeOrgActivity(
233: new TimeSpan(start, end),
234: oiElements[ACTIVITY_INDEX].getStringObject(),
235: oiElements[LOCATION_INDEX].getStringObject(),
236: oiElements[OPTEMPO_INDEX].getStringObject(),
237: myOpCon);
238: timeSpanSet.add(orgActivity);
239: minStart = end;
240: }
241: }
242:
243: protected static class OrgInfoElements {
244: Iterator iterator;
245: OrgInfoElement current = null;
246: String type;
247:
248: OrgInfoElements(TimeSpanSet tss, String type) {
249: iterator = tss.iterator();
250: this .type = type;
251: }
252:
253: public boolean isFinished() {
254: return current == null && !iterator.hasNext();
255: }
256:
257: public OrgInfoElement endsAfter(long start) {
258: while (current == null || current.getEndTime() <= start) {
259: if (iterator.hasNext()) {
260: current = (OrgInfoElement) iterator.next();
261: } else {
262: return null; // Exhausted
263: }
264: }
265: return current;
266: }
267:
268: public String getStringObject() {
269: return current.getStringObject();
270: }
271:
272: public String getType() {
273: return type;
274: }
275: }
276:
277: protected static class OrgInfoElement implements
278: org.cougaar.util.TimeSpan {
279: private Object myObject;
280: private TimeSpan timeSpan;
281:
282: public OrgInfoElement(Object object, long baseTime,
283: long startDelta, long endDelta) {
284: long startTime = baseTime + (startDelta * 3600000); //milliseconds per hour
285: long endTime = baseTime + (endDelta * 3600000);
286: timeSpan = new TimeSpan(startTime, endTime);
287: myObject = object;
288: }
289:
290: public TimeSpan getTimeSpan() {
291: return timeSpan;
292: }
293:
294: public long getStartTime() {
295: return timeSpan.getStartTime();
296: }
297:
298: public long getEndTime() {
299: return timeSpan.getEndTime();
300: }
301:
302: public String getStringObject() {
303: return (String) myObject;
304: }
305:
306: public String toString() {
307: return myObject + "(" + timeSpan + ")";
308: }
309: }
310:
311: protected static SimpleDateFormat dateFormat = new SimpleDateFormat(
312: "MM/dd/yy HH:mm");
313:
314: protected static String formatDate(long time) {
315: return formatDate(new Date(time));
316: }
317:
318: protected static String formatDate(Date date) {
319: return dateFormat.format(date);
320: }
321: }
|