Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2003 Regents of the University of California.
4
 *
5
 * Author: Matthew Perry 
6
 * '$Date: 2011-01-21 15:08:31 -0800 (Fri, 21 Jan 2011) $'
7
 * '$Revision: 5829 $'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat.spatial;
24

    
25
import org.geotools.data.shapefile.ShapefileDataStore;
26
import org.geotools.data.FeatureStore;
27
import org.geotools.data.DefaultTransaction;
28
import org.geotools.data.Transaction;
29
import org.geotools.filter.CompareFilter;
30
import org.geotools.filter.FilterFactory;
31
import org.geotools.filter.FilterFactoryFinder;
32
import org.geotools.filter.IllegalFilterException;
33
import org.geotools.feature.FeatureCollection;
34
import org.geotools.feature.FeatureCollections;
35
import org.opengis.feature.simple.SimpleFeature;
36
import org.opengis.feature.simple.SimpleFeatureType;
37

    
38
import org.apache.log4j.Logger;
39

    
40
import java.io.File;
41
import java.io.IOException;
42

    
43
import java.net.URI;
44
import java.net.URL;
45
import java.net.MalformedURLException;
46

    
47
import edu.ucsb.nceas.metacat.properties.PropertyService;
48

    
49
/**
50
 * Class providing direct read/write access to the
51
 * persistent spatial cache.
52
 */
53
public class SpatialDataset {
54

    
55
  private static SpatialFeatureSchema featureSchema = new SpatialFeatureSchema();
56
  private static ShapefileDataStore polygonStore = null;
57
  private static ShapefileDataStore pointStore = null;
58
  private static FeatureStore featureStore = null;
59
 
60
  
61
  //public String polygonShpUri = PropertyService.getProperty("certPath") + "data/metacat_shps/data_bounds.shp";
62
  //public String pointShpUri = PropertyService.getProperty("certPath")+ "data/metacat_shps/data_points.shp";
63

    
64
  FeatureCollection polygonCollection = FeatureCollections.newCollection();
65
  FeatureCollection pointCollection = FeatureCollections.newCollection();
66

    
67
  private static Logger log =
68
      Logger.getLogger(SpatialDataset.class.getName());
69

    
70
  /**
71
   *  empty constructor for SpatialDataset
72
   */
73
  public SpatialDataset() throws IOException {
74
	  
75
	  polygonStore = new ShapefileDataStore( (new File( featureSchema.polygonShpUri)).toURL() );
76
	  pointStore = new ShapefileDataStore( (new File( featureSchema.pointShpUri)).toURL() );
77
    
78
  }
79

    
80
  /**
81
   * Adds a new feature (from a SpatialDocument)
82
   * This is faster than insertOrUpdate but 
83
   * relying on this method might cause duplication
84
   * of docids in the spatial cache. Therefore, its really only useful when 
85
   * regenerating the entire cache.
86
   *
87
   * @param geomType The kind of feature to be added. Currently "polygon" and "point" supported.
88
   * @param feature The geotools feature to be added to the spatial cache.
89
   */ 
90
  public void add( String geomType, SimpleFeature feature ) {
91
     if( geomType.equals("polygon") ) {
92
         // Check if feature actually is a multipolygon
93
         if( feature != null) 
94
             polygonCollection.add( feature );
95
         
96
     } else if( geomType.equals("point") ) {
97
         // Check if feature actually is a multipoint
98
         if( feature != null) 
99
             pointCollection.add( feature );
100
     }
101
  }
102

    
103
  /**
104
   * Deletes given docid from the spatial cache.
105
   *
106
   * @param geomType The kind of feature to be added. Currently "polygon" and "point" supported.
107
   * @param docid The document to be deleted from the spatial cache.
108
   */
109
  public void delete( String geomType, String docid ) throws IOException {
110

    
111
    FilterFactory filterFactory = FilterFactoryFinder.createFilterFactory();
112
    CompareFilter filter = null;
113
    FeatureStore fStore = null;
114
    ShapefileDataStore dStore = null;
115

    
116
    try {
117
        // Create the filter
118
        filter = filterFactory.createCompareFilter(CompareFilter.COMPARE_EQUALS);
119
        filter.addLeftValue(filterFactory.createAttributeExpression("docid"));
120
        filter.addRightValue(filterFactory.createLiteralExpression(docid));
121
    } catch (IllegalFilterException e) {
122
        e.printStackTrace();
123
        throw new IOException(e.getMessage());
124
    }
125

    
126
    if( geomType.equals("polygon") ) {
127
    	deleteFromDataStore(polygonStore, filter, docid);
128
     }else if( geomType.equals("point") ) {
129
    	 deleteFromDataStore(pointStore, filter, docid);    
130
     }
131
     else
132
     {
133
    	 throw new IOException("Unkown Geo Type "+geomType);
134
     }
135

    
136
    
137

    
138
  }
139
  
140
  /*
141
   * Delete a feature from given spatail data store
142
   */
143
  private void deleteFromDataStore(ShapefileDataStore dStore, CompareFilter filter, String docid) 
144
                                     throws IOException
145
  {
146
	  if (dStore != null && filter != null)
147
	  {
148
		  synchronized(dStore)
149
		  {
150
			  // Begin new transaction
151
			    Transaction t = new DefaultTransaction("handle");
152
			    t.putProperty( "updating spatial cache", new Integer(7) );
153
			    String lockId = "SpatialDataset.delete";
154
			    FeatureStore fStore = (FeatureStore) dStore.getFeatureSource(dStore.getTypeNames()[0]);
155
			    try {
156
			        
157
			    	if (fStore != null)
158
			    	{
159
				        // Initiate the transaction
160
				        fStore.setTransaction( t );
161
				        t.addAuthorization( lockId );
162
				        
163
				        // Remove old feature
164
				        fStore.removeFeatures( filter );
165
		
166
				        // Commit changes to shapefile
167
				        t.commit();
168
				        log.info(" Delete docid " + docid + " from spatial cache");
169
			    	}
170
			    	else
171
			    	{
172
			    		log.error("Feature store is null");
173
			    	}
174
			       
175
	
176
			    } catch (MalformedURLException e) {
177
			        e.printStackTrace();
178
			        t.rollback(); // cancel opperations
179
			    } catch (IOException e) {
180
			        e.printStackTrace();
181
			        t.rollback(); // cancel opperations
182
			    } finally {
183
			        // Close out the transaction
184
			        t.close();
185
			    }
186
		  }
187
	  }
188
	  else if (dStore == null)
189
	  {
190
		  log.error("Shape file store is null");
191
	  }
192
  }
193
  
194
  
195

    
196
  /**
197
   * Either inserts or updates the spatial cache with the new
198
   * spatial document depending on if it currently exists.
199
   * Docid is also passed in for quicker searching.
200
   *
201
   * @param geomType The kind of feature to be added. Currently "polygon" and "point" supported.
202
   * @param feature The geotools feature to be added to the spatial cache.
203
   * @param docid The document id to be inserted or updated. Used to filter for existing features.
204
   */
205
  public void insertOrUpdate( String geomType, SimpleFeature feature, String docid ) throws IOException {
206
    
207
    FeatureCollection fColl = FeatureCollections.newCollection();
208
    FilterFactory filterFactory = FilterFactoryFinder.createFilterFactory();
209
    CompareFilter filter = null;
210
    FeatureStore fStore = null;
211
    ShapefileDataStore dStore = null;
212

    
213
    // Explain why geotools fails to create the projection info from the shapefile
214
    //log.info( " The '.prj' errors below are related to a geotools bug " +
215
    //          " (http://jira.codehaus.org/browse/GEOT-604) and can be ignored");
216

    
217
    try {
218
        // Create the filter
219
        filter = filterFactory.createCompareFilter(CompareFilter.COMPARE_EQUALS);
220
        filter.addLeftValue(filterFactory.createAttributeExpression("docid"));
221
        filter.addRightValue(filterFactory.createLiteralExpression(docid));
222
    } catch (IllegalFilterException e) {
223
        e.printStackTrace();
224
        throw new IOException(e.getMessage());
225
    }
226

    
227
    if( geomType.equals("polygon") ) {
228
    	log.debug("SpatialDataset.insertOrUpdate - inserting or updating polygon store");
229
        insertOrUpdateDataStore(polygonStore,filter, feature, fColl, docid);
230
    } else if( geomType.equals("point") ) {
231
    	log.debug("SpatialDataset.insertOrUpdate - inserting or updating point store");
232
    	insertOrUpdateDataStore(pointStore,filter, feature, fColl, docid);
233
    }else{
234
   	    throw new IOException("Unkown Geo Type "+geomType);
235
    }
236
    
237

    
238
       
239

    
240

    
241
  }
242
  
243
  /*
244
   * Insert or update new feature in shape file
245
   */
246
  private void insertOrUpdateDataStore(ShapefileDataStore dStore, CompareFilter filter, SimpleFeature feature, 
247
		                                FeatureCollection fColl, String docid) throws IOException
248
  {
249
	  if (dStore != null && filter != null && feature != null && fColl != null)
250
	  {
251
		  synchronized(dStore)
252
		  {
253
//			 Begin new transaction
254
			    Transaction t = new DefaultTransaction("handle");
255
			    t.putProperty( "updating spatial cache", new Integer(7) );
256
			    String lockId = "SpatialDataset.insertOrUpdate";
257
			    
258
			    try {
259
			    	FeatureStore fStore = (FeatureStore) dStore.getFeatureSource(dStore.getTypeNames()[0]);
260
			        if( fStore != null) {
261
			        	// Initiate the transaction
262
				        fStore.setTransaction( t );
263
				        t.addAuthorization( lockId );
264
			            // Remove old feature
265
			            fStore.removeFeatures( filter );
266

    
267
			            // Create new feature collection then add it to feature Store
268
			            fColl.add( feature );
269
			            fStore.addFeatures(fColl);
270

    
271
			            // Commit changes to shapefile
272
			            t.commit();
273
			            log.info(" Insert or Update docid " + docid + " from spatial cache");
274
			        }
275
			        else
276
			    	{
277
			    		log.error("Feature store is null");
278
			    	}
279

    
280

    
281
			    } catch (MalformedURLException e) {
282
			        e.printStackTrace();
283
			        t.rollback(); // cancel operations
284
			    } catch (IOException e) {
285
			        e.printStackTrace();
286
			        t.rollback(); // cancel operations
287
			    } catch (Exception e) {
288
			    	e.printStackTrace();
289
			        t.rollback(); // cancel operations
290
			    } finally {
291
			        // Close out the transaction
292
			        t.close();
293
			    }
294

    
295
		  }
296
	  }
297
	  else if (dStore == null)
298
	  {
299
		  log.error("Shape file store is null");
300
	  }
301
  }
302

    
303
  /**
304
   * Saves the SpatialDataset object to the spatial cache.
305
   */
306
  public void save() {
307
         // Save Polygons 
308
         try {
309
             //URL anURL = (new File( featureSchema.polygonShpUri )).toURL();
310
             //ShapefileDataStore polygonDatastore = new ShapefileDataStore(anURL);
311
        	 if (polygonStore != null)
312
        	 {	 
313
        		 
314
	        	 synchronized(polygonStore)
315
	        	 {
316
		             SimpleFeatureType polygonType = featureSchema.getPolygonFeatureType();
317
		             polygonStore.createSchema( polygonType );
318
		             FeatureStore polygonFeatureStore = (FeatureStore) polygonStore.getFeatureSource( polygonType.getTypeName() );
319
		             polygonFeatureStore.addFeatures( polygonCollection );
320
		             log.info(" ---- Polygons saved to " + featureSchema.polygonShpUri );
321
	        	 }
322
        	 }
323
        	 else
324
        	 {
325
        		log.error("Couldn't find the polygon shape file store"); 
326
        	 }
327
         } catch(java.net.MalformedURLException e) {
328
             log.error("Malformed URL Exception : "+e);
329
         } catch(java.io.IOException e) {
330
             log.error("IO Exception : "+e);
331

    
332
         }
333

    
334
         // Save Points
335
         try {
336
             //URL anURL = (new File( featureSchema.pointShpUri )).toURL();
337
             //ShapefileDataStore pointDatastore = new ShapefileDataStore(anURL);
338
        	 if (pointStore != null)
339
        	 {
340
	        	 synchronized(pointStore)
341
	        	 {
342
		             SimpleFeatureType pointsType = featureSchema.getPointFeatureType();
343
		             pointStore.createSchema( pointsType );
344
		             FeatureStore pointFeatureStore = (FeatureStore) pointStore.getFeatureSource( pointsType.getTypeName() );
345
		             pointFeatureStore.addFeatures( pointCollection );
346
		             log.info(" ---- Polygons saved to " + featureSchema.pointShpUri );
347
	        	 }
348
        	 }
349
        	 else
350
        	 {
351
        		 log.error("Couldn't find the shape point file store");
352
        	 }
353
         } catch(java.net.MalformedURLException e) {
354
             log.error("Malformed URL Exception : "+e);
355
         } catch(java.io.IOException e) {
356
             log.error("IO Exception : "+e);
357
         }
358
  }
359
  
360
 
361

    
362
}
(2-2/8)