001: /*
002: * This file is part of the GeOxygene project source files.
003: *
004: * GeOxygene aims at providing an open framework which implements OGC/ISO specifications for
005: * the development and deployment of geographic (GIS) applications. It is a open source
006: * contribution of the COGIT laboratory at the Institut Géographique National (the French
007: * National Mapping Agency).
008: *
009: * See: http://oxygene-project.sourceforge.net
010: *
011: * Copyright (C) 2005 Institut Géographique National
012: *
013: * This library is free software; you can redistribute it and/or modify it under the terms
014: * of the GNU Lesser General Public License as published by the Free Software Foundation;
015: * either version 2.1 of the License, or any later version.
016: *
017: * This library is distributed in the hope that it will be useful, but WITHOUT ANY
018: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
019: * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser General Public License along with
022: * this library (see file LICENSE if present); if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: *
025: */
026:
027: package fr.ign.cogit.geoxygene.datatools.oracle;
028:
029: import java.io.File;
030: import java.math.BigDecimal;
031: import java.sql.Connection;
032: import java.sql.ResultSet;
033: import java.sql.Statement;
034: import java.util.Iterator;
035: import java.util.List;
036:
037: import oracle.sdoapi.OraSpatialManager;
038:
039: import org.apache.ojb.broker.core.PersistenceBrokerHandle;
040: import org.apache.ojb.broker.core.PoolablePersistenceBroker;
041: import org.apache.ojb.broker.metadata.DescriptorRepository;
042: import org.apache.ojb.broker.metadata.MetadataManager;
043: import org.apache.ojb.odmg.HasBroker;
044: import org.odmg.DList;
045: import org.odmg.OQLQuery;
046:
047: import fr.ign.cogit.geoxygene.datatools.Geodatabase;
048: import fr.ign.cogit.geoxygene.datatools.ojb.*;
049: import fr.ign.cogit.geoxygene.feature.FT_Feature;
050: import fr.ign.cogit.geoxygene.feature.FT_FeatureCollection;
051: import fr.ign.cogit.geoxygene.spatial.geomroot.GM_Object;
052:
053: /**
054: * Implementation d'une Geodatabase
055: * utilisant OJB comme mappeur
056: * et Oracle comme SGBDR geographique.
057: *
058: * @author Thierry Badard & Arnaud Braun
059: * @version 1.1
060: */
061:
062: public class GeodatabaseOjbOracle extends GeodatabaseOjb implements
063: Geodatabase {
064:
065: /** Constructeur direct. */
066: public GeodatabaseOjbOracle() {
067: super ();
068: updateConnection();
069: initGeomMetadata();
070: }
071:
072: /** Constructeur en specialisant GeodatabaseOjb.
073: * Usage interne, appele par GeodatabaseOjbFactory. */
074: public GeodatabaseOjbOracle(GeodatabaseOjb ojb) {
075: _conn = ojb.getConnection();
076: _odmg = ojb.getODMGImplementation();
077: _db = ojb.getODMGDatabase();
078: _tx = ojb.getODMGTransaction();
079: _metadataList = ojb.getMetadata();
080: updateConnection();
081: initGeomMetadata();
082: }
083:
084: /** Passe des parametres statiques a la classe de conversion GeomGeOxygene2Oracle. */
085: private void updateConnection() {
086: try {
087: GeomGeOxygene2Oracle.CONNECTION = _conn;
088: GeomGeOxygene2Oracle.GF = OraSpatialManager
089: .getGeometryFactory();
090: GeomGeOxygene2Oracle.SRM = OraSpatialManager
091: .getSpatialReferenceManager();
092: } catch (Exception e) {
093: e.printStackTrace();
094: }
095: }
096:
097: /** Renseigne l'attribut _metadataList. */
098: private void initGeomMetadata() {
099: OracleSpatialQuery.initGeomMetadata(_metadataList, _conn);
100: }
101:
102: /** Charge tous les FT_Feature de la classe theClass intersectant le GM_Object geom, dans la classe FT_FeatureCollection.
103: A appeler a l'interieur d'une transaction ouverte.
104: La classe theClass doit etre une sous-classe de FT_Feature, sinon renvoie une liste vide. */
105: public FT_FeatureCollection loadAllFeatures(Class featureClass,
106: GM_Object geom) {
107: FT_FeatureCollection result = new FT_FeatureCollection();
108: if ((FT_Feature.class).isAssignableFrom(featureClass)) {
109: // on cherche la liste des identifiants
110: List idList = OracleSpatialQuery.loadAllFeatures(this ,
111: featureClass, geom);
112: // charge tous les objets dont on a trouve l'identifiant
113: if (idList.size() > 0) {
114: String query = createInQuery(idList, featureClass
115: .getName());
116: OQLQuery oqlQuery = _odmg.newOQLQuery();
117: try {
118: oqlQuery.create(query);
119: DList list = (DList) oqlQuery.execute();
120: Iterator iter = list.iterator();
121: while (iter.hasNext()) {
122: FT_Feature feature = (FT_Feature) iter.next();
123: result.add(feature);
124: }
125: } catch (Exception e) {
126: e.printStackTrace();
127: }
128: }
129: } else {
130: System.out
131: .println("loadAllFeatures() : La classe passee en parametre n'est pas une sous-classe de FT_Feature");
132: }
133: return result;
134: }
135:
136: /** Charge tous les FT_Feature de la classe theClass intersectant le GM_Object geom, dans la classe featureListClass.
137: A appeler a l'interieur d'une transaction ouverte.
138: La classe theClass doit etre une sous-classe de FT_Feature, sinon renvoie une liste vide.
139: La classe featureListClass doit etre un sous classe de FT_FeatureCollection.*/
140: public Object loadAllFeatures(Class featureClass,
141: Class featureListClass, GM_Object geom) {
142: Object result = null;
143: try {
144: result = featureListClass.newInstance();
145: } catch (Exception e) {
146: e.printStackTrace();
147: }
148: if ((FT_Feature.class).isAssignableFrom(featureClass)) {
149: // on cherche la liste des identifiants
150: List idList = OracleSpatialQuery.loadAllFeatures(this ,
151: featureClass, geom);
152: // charge tous les objets dont on a trouve l'identifiant
153: if (idList.size() > 0) {
154: String query = createInQuery(idList, featureClass
155: .getName());
156: OQLQuery oqlQuery = _odmg.newOQLQuery();
157: try {
158: oqlQuery.create(query);
159: DList list = (DList) oqlQuery.execute();
160: Iterator iter = list.iterator();
161: while (iter.hasNext()) {
162: FT_Feature feature = (FT_Feature) iter.next();
163: result.getClass().getMethod("add",
164: new Class[] { FT_Feature.class })
165: .invoke(result,
166: new Object[] { feature });
167: }
168: } catch (Exception e) {
169: e.printStackTrace();
170: }
171: }
172: } else {
173: System.out
174: .println("loadAllFeatures() : La classe passee en parametre n'est pas une sous-classe de FT_Feature");
175: }
176: return result;
177: }
178:
179: /** Charge tous les FT_Feature de la classe theClass a une distance dist du GM_Object geom, dans la classe FT_FeatureCollection.
180: Si geom est la geometrie d'un FT_Feature de theClass, alors ce FT_Feature appartiendra au resultat.
181: A appeler a l'interieur d'une transaction ouverte.
182: La classe theClass doit etre une sous-classe de FT_Feature, sinon renvoie une liste vide.*/
183: public FT_FeatureCollection loadAllFeatures(Class featureClass,
184: GM_Object geom, double dist) {
185: FT_FeatureCollection result = new FT_FeatureCollection();
186: if ((FT_Feature.class).isAssignableFrom(featureClass)) {
187: // on cherche la liste des identifiants
188: List idList = OracleSpatialQuery.loadAllFeatures(this ,
189: featureClass, geom, dist);
190: // charge tous les objets dont on a trouve l'identifiant
191: if (idList.size() > 0) {
192: String query = createInQuery(idList, featureClass
193: .getName());
194: OQLQuery oqlQuery = _odmg.newOQLQuery();
195: try {
196: oqlQuery.create(query);
197: DList list = (DList) oqlQuery.execute();
198: Iterator iter = list.iterator();
199: while (iter.hasNext()) {
200: FT_Feature feature = (FT_Feature) iter.next();
201: result.add(feature);
202: }
203: } catch (Exception e) {
204: e.printStackTrace();
205: }
206: }
207: } else {
208: System.out
209: .println("loadAllFeatures() : La classe passee en parametre n'est pas une sous-classe de FT_Feature");
210: }
211: return result;
212: }
213:
214: /** Charge tous les FT_Feature de la classe theClass a une distance dist du GM_Object geom, dans la classe featureListClass.
215: Si geom est la geometrie d'un FT_Feature de theClass, alors ce FT_Feature appartiendra au resultat.
216: A appeler a l'interieur d'une transaction ouverte.
217: La classe theClass doit etre une sous-classe de FT_Feature, sinon renvoie une liste vide.
218: La classe featureListClass doit etre un sous classe de FT_FeatureCollection.*/
219: public Object loadAllFeatures(Class featureClass,
220: Class featureListClass, GM_Object geom, double dist) {
221: Object result = null;
222: try {
223: result = (FT_FeatureCollection) featureListClass
224: .newInstance();
225: } catch (Exception e) {
226: e.printStackTrace();
227: }
228: if ((FT_Feature.class).isAssignableFrom(featureClass)) {
229: // on cherche la liste des identifiants
230: List idList = OracleSpatialQuery.loadAllFeatures(this ,
231: featureClass, geom, dist);
232: // charge tous les objets dont on a trouve l'identifiant
233: if (idList.size() > 0) {
234: String query = createInQuery(idList, featureClass
235: .getName());
236: OQLQuery oqlQuery = _odmg.newOQLQuery();
237: try {
238: oqlQuery.create(query);
239: DList list = (DList) oqlQuery.execute();
240: Iterator iter = list.iterator();
241: while (iter.hasNext()) {
242: FT_Feature feature = (FT_Feature) iter.next();
243: result.getClass().getMethod("add",
244: new Class[] { FT_Feature.class })
245: .invoke(result,
246: new Object[] { feature });
247: }
248: } catch (Exception e) {
249: e.printStackTrace();
250: }
251: }
252: } else {
253: System.out
254: .println("loadAllFeatures() : La classe passee en parametre n'est pas une sous-classe de FT_Feature");
255: }
256: return result;
257: }
258:
259: /** Cree une requete pour permettre de charger tous les objets a partir d'une liste d'identifants.
260: * Usage interne. */
261: private String createInQuery(List idList, String className) {
262: StringBuffer strBuff = new StringBuffer("select x from "
263: + className + " where id in (");
264: Iterator i = idList.iterator();
265: while (i.hasNext()) {
266: int k = ((BigDecimal) i.next()).intValue();
267: strBuff.append(k);
268: strBuff.append(",");
269: }
270: String result = strBuff.toString();
271: result = result.substring(0, result.length() - 1);
272: result = result + ")";
273: return result;
274: }
275:
276: /** Calcule DANS LE SGBD l'emprise la table mappee avec la classe.
277: La classe doit heriter de FT_Feature, la table doit contenir une geometrie. */
278: public void mbr(Class clazz) {
279: OracleSpatialQuery.mbr(this , clazz);
280: }
281:
282: /** Calcule DANS LE SGBD un index spatial sur la table mappee avec la classe (R-Tree).
283: La classe doit heriter de FT_Feature, la table doit contenir une geometrie. */
284: public void spatialIndex(Class clazz) {
285: OracleSpatialQuery.spatialIndex(this , clazz);
286: }
287:
288: /** Renvoie le nombre d'objets persistants de la classe theClass.
289: A appeler a l'interieur d'une transaction ouverte. */
290: public int countObjects(Class theClass) {
291: String tableName = getMetadata(theClass).getTableName();
292: String query = "select count(*) from " + tableName;
293: BigDecimal nn = null;
294: try {
295: Connection conn = getConnection();
296: Statement stm = conn.createStatement();
297: ResultSet rs = (ResultSet) stm.executeQuery(query);
298: while (rs.next())
299: nn = (BigDecimal) rs.getObject(1);
300: stm.close();
301: } catch (Exception e) {
302: e.printStackTrace();
303: }
304: return nn.intValue();
305: }
306:
307: /** Renvoie l'identifiant maximum de la classe theClass.
308: ATTENTION : La classe passee en parametre doit avoir un champ "id" de type int (marche pour les FT_Feature).
309: A appeler a l'interieur d'une transaction ouverte. */
310: public int maxId(Class theClass) {
311: String idColumnName = getMetadata(theClass).getIdColumnName();
312: String tableName = getMetadata(theClass).getTableName();
313: String query = "select max(" + idColumnName + ") from "
314: + tableName;
315: BigDecimal nn = null;
316: try {
317: Connection conn = getConnection();
318: Statement stm = conn.createStatement();
319: ResultSet rs = (ResultSet) stm.executeQuery(query);
320: while (rs.next())
321: nn = (BigDecimal) rs.getObject(1);
322: stm.close();
323: } catch (Exception e) {
324: e.printStackTrace();
325: }
326: return nn.intValue();
327: }
328:
329: /** Renvoie l'identifiant minimum de la classe theClass.
330: ATTENTION : La classe passee en parametre doit avoir un champ "id" de type int (marche pour les FT_Feature).
331: A appeler a l'interieur d'une transaction ouverte. */
332: public int minId(Class theClass) {
333: String idColumnName = getMetadata(theClass).getIdColumnName();
334: String tableName = getMetadata(theClass).getTableName();
335: String query = "select min(" + idColumnName + ") from "
336: + tableName;
337: BigDecimal nn = null;
338: try {
339: Connection conn = getConnection();
340: Statement stm = conn.createStatement();
341: ResultSet rs = (ResultSet) stm.executeQuery(query);
342: while (rs.next())
343: nn = (BigDecimal) rs.getObject(1);
344: stm.close();
345: } catch (Exception e) {
346: e.printStackTrace();
347: }
348: return nn.intValue();
349: }
350:
351: /** renvoie le type de SGBD associe. */
352: public int getDBMS() {
353: return Geodatabase.ORACLE;
354: }
355:
356: /** Utilise par EsayLoader pour recharger un fichier de mapping qui a ete modifie. */
357: public void refreshRepository(File newRepository) throws Exception {
358: MetadataManager mm = MetadataManager.getInstance();
359: DescriptorRepository rd = mm
360: .readDescriptorRepository(newRepository.getPath());
361: mm.setDescriptor(rd, true);
362: begin();
363: PersistenceBrokerHandle pbh = (PersistenceBrokerHandle) ((HasBroker) _tx)
364: .getBroker();
365: PoolablePersistenceBroker ppb = (PoolablePersistenceBroker) pbh
366: .getDelegate();
367: GeOxygenePersistenceBrokerImpl pbi = (GeOxygenePersistenceBrokerImpl) ppb
368: .getDelegate();
369: pbi.refresh();
370: commit();
371: initMetadata();
372: initGeomMetadata();
373: }
374:
375: }
|