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.feature;
028:
029: import java.util.ArrayList;
030: import java.util.Iterator;
031: import java.util.List;
032:
033: import fr.ign.cogit.geoxygene.feature.Population;
034:
035: import fr.ign.cogit.geoxygene.spatial.geomroot.GM_Object;
036: import fr.ign.cogit.geoxygene.spatial.toporoot.TP_Object;
037:
038: /**
039: * Classe mère pour toute classe d'éléments ayant une réalité géographique.
040: * Par défaut, porte une géométrie et une topologie, qui peuvent être nulles.
041: *
042: * <P> A REVOIR plus tard : ne plus porter de geometrie ni de topologie par defaut,
043: * et permettre le choix du nom de l'attribut portant geometrie et topologie.
044: *
045: * @author Thierry Badard & Arnaud Braun
046: * @version 1.0
047: *
048: */
049:
050: public abstract class FT_Feature implements Cloneable {
051:
052: protected int id;
053:
054: /** Renvoie l'identifiant. NB: l'identifiant n'est rempli automatiquement que pour les objets persistants */
055: public int getId() {
056: return id;
057: }
058:
059: /** Affecte un identifiant (ne pas utiliser si l'objet est persistant car cela est automatique) */
060: public void setId(int Id) {
061: id = Id;
062: }
063:
064: protected GM_Object geom = null;
065:
066: /** Renvoie une geometrie. */
067: public GM_Object getGeom() {
068: return geom;
069: }
070:
071: /** Affecte une geometrie (et met à jour les éventuels index concernés. */
072: public void setGeom(GM_Object g) {
073: boolean geomAvant = false;
074: if (geom != null)
075: geomAvant = true;
076: geom = g;
077: Iterator itFC = this .getFeatureCollections().iterator();
078: while (itFC.hasNext()) {
079: FT_FeatureCollection fc = (FT_FeatureCollection) itFC
080: .next();
081: if (fc.hasSpatialIndex()) {
082: if (fc.getSpatialIndex().hasAutomaticUpdate()) {
083: if (geomAvant)
084: fc.getSpatialIndex().update(this , 0);
085: else
086: fc.getSpatialIndex().update(this , 1);
087: }
088: }
089: }
090: }
091:
092: /** Renvoie true si une geometrie existe, false sinon. */
093: public boolean hasGeom() {
094: if (geom == null)
095: return false;
096: else
097: return true;
098: }
099:
100: protected TP_Object topo = null;
101:
102: /** Renvoie une topologie. */
103: public TP_Object getTopo() {
104: return topo;
105: }
106:
107: /** Affecte une topologie. */
108: public void setTopo(TP_Object t) {
109: topo = t;
110: }
111:
112: /** Renvoie true si une topologie existe, false sinon. */
113: public boolean hasTopo() {
114: if (topo == null)
115: return false;
116: else
117: return true;
118: }
119:
120: /** Clonage avec clonage de la geometrie. */
121: public FT_Feature cloneGeom() {
122: FT_Feature result = (FT_Feature) this .clone();
123: result.setGeom((GM_Object) this .getGeom().clone());
124: return result;
125: }
126:
127: /** Clonage sans clonage de la geometrie. */
128: public Object clone() {
129: try {
130: return super .clone();
131: } catch (Exception e) {
132: e.printStackTrace();
133: return null;
134: }
135: }
136:
137: /** Lien n-m bidirectionnel vers FT_FeatureCollection. */
138: private List featurecollections = new ArrayList();
139:
140: /** Renvoie toutes les FT_FeatureCollection auquelles appartient this. */
141: public List getFeatureCollections() {
142: return featurecollections;
143: }
144:
145: /** Renvoie la i-eme FT_FeatureCollection a laquelle appartient this. */
146: public FT_FeatureCollection getFeatureCollection(int i) {
147: return (FT_FeatureCollection) featurecollections.get(i);
148: }
149:
150: /** Population a laquelle appartient this.
151: * Renvoie null si this n'appartient a aucune population.
152: * NB : normalement, this appartient à une seule collection.
153: * Si ce n'est pas le cas, une seule des collections est renvoyée au hasard (la première de la liste).
154: */
155: public Population getPopulation() {
156: Iterator it = featurecollections.iterator();
157: while (it.hasNext()) {
158: Object o = it.next();
159: if (o instanceof Population)
160: return (Population) o;
161: }
162: return null;
163: }
164:
165: /** Définit la population en relation, et met à jour la relation inverse.
166: * ATTENTION : presistance du FT_Feature non gérée dans cette méthode.
167: */
168: /* public void setPopulation(Population O) {
169: Population old = this.getPopulation();
170: if ( old != null ) old.remove(this);
171: if ( O != null ) O.add(this);
172: }
173: */
174:
175: /** Lien bidirectionnel n-m des éléments vers eux-mêmes.
176: * Les méthodes get (sans indice) et set sont nécessaires au mapping.
177: * Les autres méthodes sont là seulement pour faciliter l'utilisation de la relation.
178: * ATTENTION: Pour assurer la bidirection, il faut modifier les listes uniquement avec ces methodes.
179: * NB: si il n'y a pas d'objet en relation, la liste est vide mais n'est pas "null".
180: * Pour casser toutes les relations, faire setListe(new ArrayList()) ou emptyListe().
181: */
182: private List correspondants = new ArrayList();
183:
184: /** Lien bidirectionnel n-m des éléments vers eux-mêmes. */
185: public List getCorrespondants() {
186: return correspondants;
187: }
188:
189: /** Lien bidirectionnel n-m des éléments vers eux-mêmes. */
190: public void setCorrespondants(List L) {
191: List old = new ArrayList(correspondants);
192: Iterator it1 = old.iterator();
193: while (it1.hasNext()) {
194: FT_Feature O = (FT_Feature) it1.next();
195: correspondants.remove(O);
196: O.getCorrespondants().remove(this );
197: }
198: Iterator it2 = L.iterator();
199: while (it2.hasNext()) {
200: FT_Feature O = (FT_Feature) it2.next();
201: correspondants.add(O);
202: O.getCorrespondants().add(this );
203: }
204: }
205:
206: /** Lien bidirectionnel n-m des éléments vers eux-mêmes. */
207: public FT_Feature getCorrespondant(int i) {
208: if (correspondants.size() == 0)
209: return null;
210: return (FT_Feature) correspondants.get(i);
211: }
212:
213: /** Lien bidirectionnel n-m des éléments vers eux même. */
214: public void addCorrespondant(FT_Feature O) {
215: if (O == null)
216: return;
217: correspondants.add(O);
218: O.getCorrespondants().add(this );
219: }
220:
221: /** Lien bidirectionnel n-m des éléments vers eux-mêmes. */
222: public void removeCorrespondant(FT_Feature O) {
223: if (O == null)
224: return;
225: correspondants.remove(O);
226: O.getCorrespondants().remove(this );
227: }
228:
229: /** Lien bidirectionnel n-m des éléments vers eux-mêmes. */
230: public void clearCorrespondants() {
231: Iterator it = correspondants.iterator();
232: while (it.hasNext()) {
233: FT_Feature O = (FT_Feature) it.next();
234: O.getCorrespondants().remove(this );
235: }
236: correspondants.clear();
237: }
238:
239: /** Renvoie les correspondants appartenant a la FT_FeatureCollection passee en parametre. */
240: public List getCorrespondants(FT_FeatureCollection pop) {
241: List elementsPop = pop.getElements();
242: List resultats = new ArrayList(this.getCorrespondants());
243: resultats.retainAll(elementsPop);
244: return resultats;
245: }
246:
247: }
|