Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2003 Regents of the University of California.
4
 *
5
 * Author: Matthew Perry 
6
 * '$Date: 2009-08-24 14:34:17 -0700 (Mon, 24 Aug 2009) $'
7
 * '$Revision: 5030 $'
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.feature.FeatureType;
26
import org.geotools.data.shapefile.ShapefileDataStore;
27
import org.geotools.data.FeatureStore;
28
import org.geotools.data.DefaultTransaction;
29
import org.geotools.data.Transaction;
30
import org.geotools.feature.Feature;
31
import org.geotools.filter.Filter;
32
import org.geotools.filter.CompareFilter;
33
import org.geotools.filter.FilterFactory;
34
import org.geotools.filter.FilterFactoryFinder;
35
import org.geotools.filter.IllegalFilterException;
36
import org.geotools.feature.FeatureCollection;
37
import org.geotools.feature.FeatureCollections;
38

    
39
import org.apache.log4j.Logger;
40

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

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

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

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

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

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

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

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

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

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

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

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

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

    
137
    
138

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

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

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

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

    
228
    if( geomType.equals("polygon") ) {
229
            
230
        insertOrUpdateDataStore(polygonStore,filter, feature, fColl, docid);
231
    } else if( geomType.equals("point") ) {
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, Feature 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
		             FeatureType 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
		             FeatureType 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)