001: //=============================================================================
002: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
003: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
004: //=== and United Nations Environment Programme (UNEP)
005: //===
006: //=== This program is free software; you can redistribute it and/or modify
007: //=== it under the terms of the GNU General Public License as published by
008: //=== the Free Software Foundation; either version 2 of the License, or (at
009: //=== your option) any later version.
010: //===
011: //=== This program is distributed in the hope that it will be useful, but
012: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
013: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: //=== General Public License for more details.
015: //===
016: //=== You should have received a copy of the GNU General Public License
017: //=== along with this program; if not, write to the Free Software
018: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
019: //===
020: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
021: //=== Rome - Italy. email: geonetwork@osgeo.org
022: //==============================================================================
023:
024: package org.fao.geonet.kernel.harvest.harvester.csw;
025:
026: import java.util.List;
027: import java.util.Set;
028: import jeeves.interfaces.Logger;
029: import jeeves.resources.dbms.Dbms;
030: import jeeves.server.context.ServiceContext;
031: import jeeves.utils.Xml;
032: import org.fao.geonet.GeonetContext;
033: import org.fao.geonet.constants.Geonet;
034: import org.fao.geonet.csw.common.Csw.ElementSetName;
035: import org.fao.geonet.csw.common.requests.CatalogRequest;
036: import org.fao.geonet.csw.common.requests.GetRecordByIdRequest;
037: import org.fao.geonet.csw.common.util.CswServer;
038: import org.fao.geonet.kernel.DataManager;
039: import org.fao.geonet.kernel.harvest.harvester.CategoryMapper;
040: import org.fao.geonet.kernel.harvest.harvester.GroupMapper;
041: import org.fao.geonet.kernel.harvest.harvester.Privileges;
042: import org.fao.geonet.kernel.harvest.harvester.RecordInfo;
043: import org.fao.geonet.kernel.harvest.harvester.UUIDMapper;
044: import org.jdom.Element;
045:
046: //=============================================================================
047:
048: public class Aligner {
049: //--------------------------------------------------------------------------
050: //---
051: //--- Constructor
052: //---
053: //--------------------------------------------------------------------------
054:
055: public Aligner(Logger log, ServiceContext sc, Dbms dbms,
056: CswServer server, CswParams params) {
057: this .log = log;
058: this .context = sc;
059: this .dbms = dbms;
060: this .server = server;
061: this .params = params;
062:
063: GeonetContext gc = (GeonetContext) context
064: .getHandlerContext(Geonet.CONTEXT_NAME);
065: dataMan = gc.getDataManager();
066: result = new CswResult();
067:
068: //--- setup get-record-by-id request
069:
070: request = new GetRecordByIdRequest();
071: request.setElementSetName(ElementSetName.FULL);
072:
073: CswServer.Operation oper = server
074: .getOperation(CswServer.GET_RECORD_BY_ID);
075:
076: if (oper.postUrl != null) {
077: request.setUrl(oper.postUrl);
078: request.setMethod(CatalogRequest.Method.POST);
079: } else {
080: request.setUrl(oper.getUrl);
081: request.setMethod(CatalogRequest.Method.GET);
082: }
083:
084: if (params.useAccount)
085: request.setCredentials(params.username, params.password);
086: }
087:
088: //--------------------------------------------------------------------------
089: //---
090: //--- Alignment method
091: //---
092: //--------------------------------------------------------------------------
093:
094: public CswResult align(Set<RecordInfo> records) throws Exception {
095: log.info("Start of alignment for : " + params.name);
096:
097: //-----------------------------------------------------------------------
098: //--- retrieve all local categories and groups
099: //--- retrieve harvested uuids for given harvesting node
100:
101: localCateg = new CategoryMapper(dbms);
102: localGroups = new GroupMapper(dbms);
103: localUuids = new UUIDMapper(dbms, params.uuid);
104: dbms.commit();
105:
106: //-----------------------------------------------------------------------
107: //--- remove old metadata
108:
109: for (String uuid : localUuids.getUUIDs())
110: if (!exists(records, uuid)) {
111: String id = localUuids.getID(uuid);
112:
113: log.debug(" - Removing old metadata with local id:"
114: + id);
115: dataMan.deleteMetadata(dbms, id);
116: dbms.commit();
117: result.locallyRemoved++;
118: }
119:
120: //-----------------------------------------------------------------------
121: //--- insert/update new metadata
122:
123: for (RecordInfo ri : records) {
124: result.totalMetadata++;
125:
126: String id = dataMan.getMetadataId(dbms, ri.uuid);
127:
128: if (id == null)
129: addMetadata(ri);
130: else
131: updateMetadata(ri, id);
132: }
133:
134: log.info("End of alignment for : " + params.name);
135:
136: return result;
137: }
138:
139: //--------------------------------------------------------------------------
140: //---
141: //--- Private methods : addMetadata
142: //---
143: //--------------------------------------------------------------------------
144:
145: private void addMetadata(RecordInfo ri) throws Exception {
146: Element md = retrieveMetadata(ri.uuid);
147:
148: if (md == null)
149: return;
150:
151: String schema = dataMan.autodetectSchema(md);
152:
153: if (schema == null) {
154: log
155: .debug(" - Metadata skipped due to unknown schema. uuid:"
156: + ri.uuid);
157: result.unknownSchema++;
158:
159: return;
160: }
161:
162: log.debug(" - Adding metadata with remote uuid:" + ri.uuid);
163:
164: String id = dataMan.insertMetadataExt(dbms, schema, md, context
165: .getSerialFactory(), params.uuid, ri.changeDate,
166: ri.changeDate, ri.uuid, 1, null);
167:
168: int iId = Integer.parseInt(id);
169:
170: dataMan.setTemplate(dbms, iId, "n", null);
171: dataMan.setHarvested(dbms, iId, params.uuid);
172:
173: addPrivileges(id);
174: addCategories(id);
175:
176: dbms.commit();
177: dataMan.indexMetadata(dbms, id);
178: result.addedMetadata++;
179: }
180:
181: //--------------------------------------------------------------------------
182: //--- Categories
183: //--------------------------------------------------------------------------
184:
185: private void addCategories(String id) throws Exception {
186: for (String catId : params.getCategories()) {
187: String name = localCateg.getName(catId);
188:
189: if (name == null)
190: log.debug(" - Skipping removed category with id:"
191: + catId);
192: else {
193: log.debug(" - Setting category : " + name);
194: dataMan.setCategory(dbms, id, catId);
195: }
196: }
197: }
198:
199: //--------------------------------------------------------------------------
200: //--- Privileges
201: //--------------------------------------------------------------------------
202:
203: private void addPrivileges(String id) throws Exception {
204: for (Privileges priv : params.getPrivileges()) {
205: String name = localGroups.getName(priv.getGroupId());
206:
207: if (name == null)
208: log.debug(" - Skipping removed group with id:"
209: + priv.getGroupId());
210: else {
211: log.debug(" - Setting privileges for group : "
212: + name);
213:
214: for (int opId : priv.getOperations()) {
215: name = dataMan.getAccessManager().getPrivilegeName(
216: opId);
217:
218: //--- allow only: view, dynamic, featured
219: if (opId == 0 || opId == 5 || opId == 6) {
220: log.debug(" --> " + name);
221: dataMan.setOperation(dbms, id, priv
222: .getGroupId(), opId + "");
223: } else
224: log.debug(" --> " + name + " (skipped)");
225: }
226: }
227: }
228: }
229:
230: //--------------------------------------------------------------------------
231: //---
232: //--- Private methods : updateMetadata
233: //---
234: //--------------------------------------------------------------------------
235:
236: private void updateMetadata(RecordInfo ri, String id)
237: throws Exception {
238: String date = localUuids.getChangeDate(ri.uuid);
239:
240: if (date == null)
241: log
242: .debug(" - Skipped metadata managed by another harvesting node. uuid:"
243: + ri.uuid + ", name:" + params.name);
244: else {
245: if (!ri.isMoreRecentThan(date)) {
246: log.debug(" - Metadata XML not changed for uuid:"
247: + ri.uuid);
248: result.unchangedMetadata++;
249: } else {
250: log.debug(" - Updating local metadata for uuid:"
251: + ri.uuid);
252:
253: Element md = retrieveMetadata(ri.uuid);
254:
255: if (md == null)
256: return;
257:
258: dataMan.updateMetadataExt(dbms, id, md, ri.changeDate);
259:
260: dbms
261: .execute(
262: "DELETE FROM OperationAllowed WHERE metadataId=?",
263: Integer.parseInt(id));
264: addPrivileges(id);
265:
266: dbms.execute(
267: "DELETE FROM MetadataCateg WHERE metadataId=?",
268: Integer.parseInt(id));
269: addCategories(id);
270:
271: dbms.commit();
272: dataMan.indexMetadata(dbms, id);
273: result.updatedMetadata++;
274: }
275: }
276: }
277:
278: //--------------------------------------------------------------------------
279: //---
280: //--- Private methods
281: //---
282: //--------------------------------------------------------------------------
283:
284: /** Return true if the uuid is present in the remote node */
285:
286: private boolean exists(Set<RecordInfo> records, String uuid) {
287: for (RecordInfo ri : records)
288: if (uuid.equals(ri.uuid))
289: return true;
290:
291: return false;
292: }
293:
294: //--------------------------------------------------------------------------
295:
296: private Element retrieveMetadata(String uuid) {
297: request.clearIds();
298: request.addId(uuid);
299:
300: try {
301: log.debug("Getting record from : " + request.getHost()
302: + " (uuid:" + uuid + ")");
303: Element response = request.execute();
304: log.debug("Record got:\n" + Xml.getString(response));
305:
306: List list = response.getChildren();
307:
308: //--- maybe the metadata has been removed
309:
310: if (list.size() == 0)
311: return null;
312:
313: response = (Element) list.get(0);
314:
315: return (Element) response.detach();
316: } catch (Exception e) {
317: log.warning("Raised exception while getting record : " + e);
318: result.unretrievable++;
319:
320: //--- we don't raise any exception here. Just try to go on
321: return null;
322: }
323: }
324:
325: //--------------------------------------------------------------------------
326: //---
327: //--- Variables
328: //---
329: //--------------------------------------------------------------------------
330:
331: private Logger log;
332: private ServiceContext context;
333: private Dbms dbms;
334: private CswParams params;
335: private DataManager dataMan;
336: private CswServer server;
337: private CategoryMapper localCateg;
338: private GroupMapper localGroups;
339: private UUIDMapper localUuids;
340: private CswResult result;
341:
342: private GetRecordByIdRequest request;
343: }
344:
345: //=============================================================================
|