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: //package org.cougaar.logistics.plugin.asset;
030:
031: import java.sql.ResultSet;
032: import java.sql.SQLException;
033: import java.sql.Statement;
034: import java.util.Collection;
035:
036: import org.cougaar.glm.ldm.oplan.OrgActivity;
037: import org.cougaar.glm.ldm.oplan.TimeSpan;
038: import org.cougaar.util.DBProperties;
039: import org.cougaar.util.TimeSpanSet;
040:
041: /** Reads OrgActivity for specified Oplan from a database table. Assumes it's
042: * being invoked on behalf of SQLOplanPlugin. Updates orgactivities maintained
043: * by SQLOplanPlugin.
044: */
045:
046: public class OrgCodeOrgActivityQueryHandler extends
047: NewOrgActivityQueryHandler {
048:
049: private static final int ORG_CODE_COLUMN = 7;
050: public static final String ORG_CODE = ":org_code:";
051:
052: public OrgCodeOrgActivityQueryHandler(DBProperties adbp,
053: NewOplanPlugin plugin) throws SQLException {
054: super (adbp, plugin);
055: }
056:
057: public Collection executeQueries(Statement statement)
058: throws SQLException {
059:
060: String myOrgCode = plugin.getOrgCode();
061:
062: String myRollups = computeAllRollupSuperiors(myOrgCode);
063: dbp.put(ORG_CODE, myRollups);
064:
065: String query = dbp.getQuery(QUERY_NAME, dbp);
066: String orgId = null;
067: ResultSet rs = statement.executeQuery(query);
068: TimeSpanSet opTempoSchedule = new TimeSpanSet();
069: TimeSpanSet activitySchedule = new TimeSpanSet();
070: TimeSpanSet locationSchedule = new TimeSpanSet();
071: TimeSpanSet schedule;
072: boolean firstTimeThru = true;
073: String org_code = "";
074: while (rs.next()) {
075: if (firstTimeThru) {
076: org_code = getString(rs, ORG_CODE_COLUMN); //get first org_code
077: firstTimeThru = false;
078: }
079: if (logger.isDebugEnabled()) {
080: logger.debug("Querying for OrgActivities for "
081: + myOrgCode + ", got result: OrgID="
082: + getString(rs, ORG_ID) + ": "
083: + getString(rs, ATTRIBUTE_NAME) + ", "
084: + getString(rs, ATTRIBUTE_VALUE) + ", Start: "
085: + rs.getDouble(START_HOUR) + ", End: "
086: + rs.getDouble(END_HOUR) + ", UIC: "
087: + getString(rs, ORG_CODE_COLUMN));
088: }
089: if (!org_code.equals(getString(rs, ORG_CODE_COLUMN))) { //changed to next org_code
090: break;
091: }
092: String attribute_name = getString(rs, ATTRIBUTE_NAME);
093: String attribute_value = getString(rs, ATTRIBUTE_VALUE);
094: if (orgId == null)
095: orgId = getString(rs, ORG_ID);
096: if (attribute_name.equals(myOpTempoKey)) {
097: schedule = opTempoSchedule;
098: if (!attribute_value.equals(OrgActivity.HIGH_OPTEMPO)
099: && !attribute_value
100: .equals(OrgActivity.MEDIUM_OPTEMPO)
101: && !attribute_value
102: .equals(OrgActivity.LOW_OPTEMPO)) {
103: throw new SQLException("Unrecognized op tempo "
104: + attribute_value);
105: }
106: } else if (attribute_name.equals(myActivityKey)) {
107: schedule = activitySchedule;
108: } else if (attribute_name.equals(myLocationKey)) {
109: schedule = locationSchedule;
110: } else {
111: if (logger.isErrorEnabled()) {
112: logger
113: .error("OrgCodeOrgActivityQueryHandler.processRow(): unexpected text in ATTRIBUTE_NAME column - "
114: + attribute_name);
115: }
116: continue;
117: }
118: OrgInfoElement element = new OrgInfoElement(
119: attribute_value, plugin.getCDay().getTime(),
120: (long) rs.getDouble(START_HOUR), (long) rs
121: .getDouble(END_HOUR));
122: if (schedule.intersectingSet(element).isEmpty()) {
123: if (logger.isDebugEnabled()) {
124: logger
125: .debug("OrgCodeOrgActivityQueryHandler: Adding "
126: + element);
127: }
128: schedule.add(element);
129: } else {
130: if (logger.isErrorEnabled()) {
131: logger
132: .error("OrgCodeOrgActivityQueryHandler: found more than one "
133: + attribute_value
134: + " during "
135: + formatDate(element.getStartTime())
136: + " - "
137: + formatDate(element.getEndTime()));
138: }
139: }
140: }
141: TimeSpanSet timeSpanSet = new TimeSpanSet();
142: OrgInfoElements[] oiElements = {
143: new OrgInfoElements(activitySchedule, "activity"),
144: new OrgInfoElements(locationSchedule, "location"),
145: new OrgInfoElements(opTempoSchedule, "opTempo") };
146:
147: long minStart = TimeSpan.MIN_VALUE;
148: while (true) {
149: long start = minStart;
150: long end = TimeSpan.MAX_VALUE;
151: int missing = 0;
152: int present = 0;
153: // Step all iterators/elements
154: for (int i = 0; i < oiElements.length; i++) {
155: OrgInfoElement element = oiElements[i]
156: .endsAfter(minStart);
157: if (element == null) {
158: missing++;
159: } else {
160: present++;
161: end = Math.min(end, element.getEndTime());
162: start = Math.max(start, element.getStartTime());
163: }
164: }
165: if (missing > 0) {
166: if (logger.isWarnEnabled() && present > 0) {
167: StringBuffer msg = new StringBuffer();
168: msg
169: .append("OrgCodeOrgActivityQueryHandler: missing ");
170: boolean first = true;
171: for (int i = 0; i < oiElements.length; i++) {
172: if (oiElements[i].isFinished()) {
173: if (first) {
174: first = false;
175: } else {
176: msg.append(", ");
177: }
178: msg.append(oiElements[i].getType());
179: }
180: }
181: msg.append(" between ").append(formatDate(start))
182: .append(" - ").append(formatDate(end));
183: //logger.warn(msg.toString());
184: }
185: return timeSpanSet;
186: }
187: if (start > minStart && minStart > TimeSpan.MIN_VALUE) {
188: if (logger.isInfoEnabled()) {
189: logger
190: .info("OrgActivityQueryHandler: schedule gap between "
191: + formatDate(minStart)
192: + " - "
193: + formatDate(start));
194: }
195: }
196: OrgActivity orgActivity = plugin.makeOrgActivity(
197: new TimeSpan(start, end),
198: oiElements[ACTIVITY_INDEX].getStringObject(),
199: oiElements[LOCATION_INDEX].getStringObject(),
200: oiElements[OPTEMPO_INDEX].getStringObject(), null);
201: timeSpanSet.add(orgActivity);
202: minStart = end;
203: }
204: }
205:
206: // OrgCodes reflect hierarchy of agents in length of the code.
207: // So my superiors code + 1 char at end is my code.
208: // Hence I can get all of my superiors by iteratively chopping
209: // off the last char on my orgCode
210: // Use this to find OrgActivities of my superiors, in case I dont have any
211: private String computeAllRollupSuperiors(String myOrgCode) {
212: StringBuffer sb = new StringBuffer("'" + myOrgCode + "'");
213:
214: // Spot to chop of String
215: int chopLen = myOrgCode.length() - 1;
216: // So we never enter this loop if orgCode was only 1 char
217: while (chopLen > 0) {
218: //shorten orgCode by 1 each time to get next rollup
219: String nextRollup = myOrgCode.substring(0, chopLen);
220: sb.append(", '" + nextRollup + "'");
221: chopLen--;
222: }
223: return sb.toString();
224: }
225:
226: }
|