001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.module.cg.service.impl;
017:
018: import java.io.BufferedReader;
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.io.InputStreamReader;
022: import java.net.URL;
023: import java.util.Collection;
024: import java.util.Comparator;
025: import java.util.HashMap;
026: import java.util.Map;
027: import java.util.SortedMap;
028: import java.util.TreeMap;
029:
030: import org.kuali.core.service.BusinessObjectService;
031: import org.kuali.core.service.LookupService;
032: import org.kuali.kfs.KFSPropertyConstants;
033: import org.kuali.kfs.context.SpringContext;
034: import org.kuali.module.cg.bo.Cfda;
035: import org.kuali.module.cg.service.CfdaService;
036: import org.kuali.module.cg.service.CfdaUpdateResults;
037:
038: public class CfdaServiceImpl implements CfdaService {
039:
040: private BusinessObjectService businessObjectService;
041: private static String SOURCE_URL = "http://12.46.245.173/pls/portal30/CATALOG.AGY_PROGRAM_LIST_RPT.show";
042: private static Comparator cfdaComparator;
043:
044: static {
045: cfdaComparator = new Comparator() {
046: public int compare(Object o1, Object o2) {
047: String lhs = (String) o1;
048: String rhs = (String) o2;
049: return lhs.compareTo(rhs);
050: }
051: };
052: }
053:
054: /**
055: * I know this is hack-ish. Regexes are appropriate. I just couldn't get the pattern down and didn't want to waste my time
056: * figuring it out.
057: *
058: * @param string
059: * @return
060: */
061: public String extractCfdaNumberFrom(String string) {
062: if (null == string)
063: return null;
064:
065: string = string.substring(string.indexOf("<U>") + 3);
066: string = string.substring(0, string.indexOf("</U>"));
067: return string;
068: }
069:
070: /**
071: * I know this is hack-ish. Regexes are appropriate. I just couldn't get the pattern down and didn't want to waste my time
072: * figuring it out.
073: *
074: * @param string
075: * @return
076: */
077: public String extractCfdaAgencyFrom(String string) {
078: if (null == string)
079: return null;
080:
081: string = string.substring(string.indexOf("<FONT") + 5);
082: string = string.substring(string.indexOf(">") + 1);
083: string = string.substring(0, string.indexOf("</FONT>"));
084: return string;
085: }
086:
087: /**
088: * I know this is hack-ish. Regexes are appropriate. I just couldn't get the pattern down and didn't want to waste my time
089: * figuring it out.
090: *
091: * @param string
092: * @return
093: */
094: public String extractCfdaTitleFrom(String string) {
095: if (null == string)
096: return null;
097:
098: string = string.substring(string.indexOf("<FONT") + 5);
099: string = string.substring(string.indexOf(">") + 1);
100: string = string.substring(0, string.indexOf("</FONT>"));
101: return string;
102: }
103:
104: /**
105: * @return
106: * @throws IOException
107: */
108: public SortedMap<String, Cfda> getGovCodes() throws IOException {
109: SortedMap<String, Cfda> govMap = new TreeMap<String, Cfda>();
110:
111: URL url = new URL(SOURCE_URL);
112: InputStream inputStream = url.openStream();
113: InputStreamReader screenReader = new InputStreamReader(
114: inputStream);
115: BufferedReader screen = new BufferedReader(screenReader);
116: String line = screen.readLine();
117:
118: boolean headerFound = false;
119: while (null != line) {
120: if (line.trim().equals("<TR>")) {
121:
122: // There's one match that will happen for the table header row. Skip past it.
123: if (!headerFound) {
124: headerFound = true;
125: line = screen.readLine();
126: continue;
127: }
128:
129: String number = extractCfdaNumberFrom(screen.readLine());
130: /* String agency = extractCfdaAgencyFrom( */screen
131: .readLine()/* ) */; // not used, but we still need to read the line
132: // to move past it.
133: String title = extractCfdaTitleFrom(screen.readLine());
134:
135: Cfda cfda = new Cfda();
136: cfda.setCfdaNumber(number);
137: cfda.setCfdaProgramTitleName(title);
138:
139: govMap.put(number, cfda);
140: }
141:
142: line = screen.readLine();
143: }
144: return govMap;
145: }
146:
147: /**
148: * @return
149: * @throws IOException
150: */
151: public SortedMap<String, Cfda> getKfsCodes() throws IOException {
152: Collection allCodes = businessObjectService.findAll(Cfda.class);
153:
154: SortedMap<String, Cfda> kfsMapAll = new TreeMap<String, Cfda>(
155: cfdaComparator);
156: for (Object o : allCodes) {
157: Cfda c = (Cfda) o;
158: kfsMapAll.put(c.getCfdaNumber(), c);
159: }
160: return kfsMapAll;
161: }
162:
163: /**
164: *
165: */
166: public CfdaUpdateResults update() throws IOException {
167:
168: CfdaUpdateResults results = new CfdaUpdateResults();
169: Map<String, Cfda> govMap = null;
170:
171: try {
172: govMap = getGovCodes();
173: } catch (IOException ioe) {
174: StringBuilder builder = new StringBuilder();
175: builder.append("No updates took place.\n");
176: builder.append(ioe.getMessage());
177: results.setMessage(builder.toString());
178: return results;
179: }
180: Map<String, Cfda> kfsMap = getKfsCodes();
181:
182: results.setNumberOfRecordsInKfsDatabase(kfsMap.keySet().size());
183: results.setNumberOfRecordsRetrievedFromWebSite(govMap.keySet()
184: .size());
185:
186: for (Object key : kfsMap.keySet()) {
187:
188: Cfda cfdaKfs = kfsMap.get(key);
189: Cfda cfdaGov = govMap.get(key);
190:
191: if (cfdaKfs.getCfdaMaintenanceTypeId().startsWith("M")) {
192: // Leave it alone. It's maintained manually.
193: results
194: .setNumberOfRecordsNotUpdatedBecauseManual(1 + results
195: .getNumberOfRecordsNotUpdatedBecauseManual());
196: } else if (cfdaKfs.getCfdaMaintenanceTypeId().startsWith(
197: "A")) {
198:
199: if (null == cfdaGov) {
200: if ("A".equals(cfdaKfs.getCfdaStatusCode())) {
201: cfdaKfs.setCfdaStatusCode(false);
202: businessObjectService.save(cfdaKfs);
203: results
204: .setNumberOfRecordsDeactivatedBecauseNoLongerOnWebSite(results
205: .getNumberOfRecordsDeactivatedBecauseNoLongerOnWebSite() + 1);
206: } else {
207: // Leave it alone for historical purposes
208: results
209: .setNumberOfRecrodsNotUpdatedForHistoricalPurposes(results
210: .getNumberOfRecrodsNotUpdatedForHistoricalPurposes() + 1);
211: }
212: } else {
213: if ("A".equals(cfdaKfs.getCfdaStatusCode())) {
214: cfdaKfs.setCfdaProgramTitleName(cfdaGov
215: .getCfdaProgramTitleName());
216: businessObjectService.save(cfdaKfs);
217: results
218: .setNumberOfRecordsUpdatedBecauseAutomatic(results
219: .getNumberOfRecordsUpdatedBecauseAutomatic() + 1);
220: } else if ("I".equals(cfdaKfs.getCfdaStatusCode())) {
221: cfdaKfs.setCfdaStatusCode(true);
222: cfdaKfs.setCfdaProgramTitleName(cfdaGov
223: .getCfdaProgramTitleName());
224: businessObjectService.save(cfdaKfs);
225: results.setNumberOfRecordsReActivated(results
226: .getNumberOfRecordsReActivated() + 1);
227: }
228: }
229: }
230:
231: // Remove it from the govMap so we know what codes from the govMap don't already exist in KFS.
232: govMap.remove(key);
233: }
234:
235: // What's left in govMap now is just the codes that don't exist in KFS
236: for (String key : govMap.keySet()) {
237: Cfda cfdaGov = govMap.get(key);
238: cfdaGov.setCfdaMaintenanceTypeId("Automatic");
239: cfdaGov.setCfdaStatusCode(true);
240: businessObjectService.save(cfdaGov);
241: results.setNumberOfRecordsNewlyAddedFromWebSite(results
242: .getNumberOfRecordsNewlyAddedFromWebSite() + 1);
243: }
244:
245: return results;
246: }
247:
248: public void setBusinessObjectService(
249: BusinessObjectService businessObjectService) {
250: this .businessObjectService = businessObjectService;
251: }
252:
253: public Cfda getByPrimaryId(String cfdaNumber) {
254: return (Cfda) businessObjectService.findByPrimaryKey(
255: Cfda.class, mapPrimaryKeys(cfdaNumber));
256: }
257:
258: private Map<String, Object> mapPrimaryKeys(String cfdaNumber) {
259: Map<String, Object> primaryKeys = new HashMap();
260: primaryKeys.put(KFSPropertyConstants.CFDA_NUMBER, cfdaNumber
261: .trim());
262: return primaryKeys;
263: }
264:
265: }
|