Revision 31020 branches/v2_0_0_prep/libraries/libFMap_geometries/src/org/gvsig/fmap/geom/impl/DefaultGeometryManager.java

View differences:

DefaultGeometryManager.java
35 35
import java.util.Map;
36 36

  
37 37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.GeometryException;
38 39
import org.gvsig.fmap.geom.GeometryLocator;
39 40
import org.gvsig.fmap.geom.GeometryManager;
40 41
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
......
62 63
import org.slf4j.Logger;
63 64
import org.slf4j.LoggerFactory;
64 65

  
65
import com.vividsolutions.jts.geom.GeometryFactory;
66

  
67 66
/**
68 67
 * Default implementation for the {@link GeometryManager}. When the
69 68
 * application starts, this class is registered in the
......
71 70
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
72 71
 */
73 72

  
74
public class DefaultGeometryManager implements GeometryManager{
73
public class DefaultGeometryManager implements GeometryManager {
75 74
	private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
76 75
	private double flatness = 0.8;
77
	
78
	private static GeometryManager instance;
79 76

  
80 77
	/** This list holds the unique name of all registered geometry operations.
81 78
	 * The index in which they are stored is also the operation code used to invoke each one of them */
......
91 88
	private Map geometryTypeName = new HashMap();
92 89

  
93 90
	/**
94
	 * This attribute is used to keep the relationship between type,
95
	 * subtype and GeometryType. The key is the type and the
96
	 * value is other Map with the GeometryTypes
91
	 * Matrix of geometry types by type (row) and subtype (column). This matrix
92
	 * will contain null values in the cells where a GeometryType hasn't been
93
	 * registered.
97 94
	 */
98
	private Map geometrySubtypes = new HashMap();
95
	private GeometryType[][] geometryTypes;
99 96

  
100
	/**
101
	 * This array contains all the geometry types.
102
	 */
103
	private ArrayList geometryTypeList = new ArrayList();
104

  
105 97
	/** GeometryType index counter. Each time a new geometry type (not predefined) is registered it is assigned this counter's value as index and after that
106 98
	 * it is incremented by 1 */
107 99
	private int geometryTypeIndex = 0;//Geometry.EXTENDED_GEOMTYPE_OFFSET; //65536;//2^16
108 100

  
109
	/**
110
	 * Geometry Factory
111
	 */
112
	private GeometryFactory factory = new GeometryFactory();
101
	// Initially create a matrix of 17 x 6, which are the current default
102
	// types and subtypes. If another type or subtype is registered, the
103
	// matrix will grow as needed
104
	private static final int DEFAULT_TYPES_SIZE = 17;
105
	private static final int DEFAULT_SUBTYPES_SIZE = 6;
113 106

  
114
	/**
115
	 * The GeometryManager has to have a public constructor
116
	 * that will be invoked by a extension point.
117
	 */
118 107
	public DefaultGeometryManager() {
119
		this.registerGeometryFactory(new GeometryFactory());
108
		this(DEFAULT_TYPES_SIZE, DEFAULT_SUBTYPES_SIZE);
120 109
	}
121 110

  
122
	/**
123
	 * Registers a GeometryFactory that will be used instead of the default one.
124
	 * @param factory
125
	 */
126
	private void registerGeometryFactory(GeometryFactory factory) {
127
		this.factory = factory;
111
	public DefaultGeometryManager(int initialTypesSize, int initialSubtypesSize) {
112
		geometryTypes = new GeometryType[initialTypesSize][initialSubtypesSize];
128 113
	}
129 114

  
130
	/**
131
	 * Returns the current geometry factory
132
	 * @return
133
	 */
134
	public GeometryFactory getGeometryFactory() {
135
		return factory;
136
	}
137

  
138 115
	/*
139 116
	 * (non-Javadoc)
140 117
	 * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperation, org.gvsig.fmap.geom.type.GeometryType)
......
181 158

  
182 159
	}
183 160

  
184
	/**
185
	 * Registers a GeometryOperation associated to a GeometryType.
186
	 * Returns an unique index that is used later to identify and invoke the operation.<br>
187
	 *
188
	 * By convention, the return value should be stored in a public constant within the class implementing
189
	 * the operation:<BR>
190
	 * <pre>
191
	 * public class MyOperation extends GeometryOperation {
192
	 *   public static final int CODE =
193
	 *     GeometryManager.getInstance()
194
	 *        .registerGeometryOperation("MyOperation", new MyOperation(), MyGeometry.class);
195
	 * }
196
	 * </pre>
197
	 *
198
	 * This method is only used if you have not a reference to the GeometryType associated to the
199
	 * geometry class. If you have such reference then it is slightly faster to use the method that receives
200
	 * the GeometryType.<br>
201
	 *
202
	 * @param geomOpName Operation's unique name
203
	 * @param geomOp Specific GeometryOperation's instance implementing this operation
204
	 * @param geomClass Geometry implementation class
205
	 * @return Index assigned to this operation. This index is used later to access the operation.
206
	 */
207
	private int registerGeometryOperation(String geomOpName,
208
			GeometryOperation geomOp, Class geomClass) {
161
	// /**
162
	// * Registers a GeometryOperation associated to a GeometryType.
163
	// * Returns an unique index that is used later to identify and invoke the
164
	// operation.<br>
165
	// *
166
	// * By convention, the return value should be stored in a public constant
167
	// within the class implementing
168
	// * the operation:<BR>
169
	// * <pre>
170
	// * public class MyOperation extends GeometryOperation {
171
	// * public static final int CODE =
172
	// * GeometryManager.getInstance()
173
	// * .registerGeometryOperation("MyOperation", new MyOperation(),
174
	// MyGeometry.class);
175
	// * }
176
	// * </pre>
177
	// *
178
	// * This method is only used if you have not a reference to the
179
	// GeometryType associated to the
180
	// * geometry class. If you have such reference then it is slightly faster
181
	// to use the method that receives
182
	// * the GeometryType.<br>
183
	// *
184
	// * @param geomOpName Operation's unique name
185
	// * @param geomOp Specific GeometryOperation's instance implementing this
186
	// operation
187
	// * @param geomClass Geometry implementation class
188
	// * @return Index assigned to this operation. This index is used later to
189
	// access the operation.
190
	// */
191
	// private int registerGeometryOperation(String geomOpName,
192
	// GeometryOperation geomOp, Class geomClass) {
193
	//
194
	// GeometryType geomType = getGeometryType(geomClass);
195
	// return registerGeometryOperation(geomOpName, geomOp, geomType);
196
	// }
209 197

  
210
		GeometryType geomType = getGeometryType(geomClass);
211
		return registerGeometryOperation(geomOpName, geomOp, geomType);
212
	}
198
	// /**
199
	// * Registers a GeometryOperation associated to a GeometryType.
200
	// * Returns an unique index that is used later to identify and invoke the
201
	// operation.<br>
202
	// *
203
	// * By convention, the return value should be stored in a public constant
204
	// within the class implementing
205
	// * the operation:<BR>
206
	// * <pre>
207
	// * public class MyOperation extends GeometryOperation {
208
	// * public static final int CODE =
209
	// * GeometryManager.getInstance()
210
	// * .registerGeometryOperation("MyOperation", MyOperation.class,
211
	// myGeomType);
212
	// * }
213
	// * </pre>
214
	// *
215
	// * @param geomOpName Operation's unique name
216
	// * @param geomOpClass GeometryOperation class
217
	// * @param geomType GeometryType instance to which this operation should be
218
	// associated
219
	// * @return Index assigned to this operation. This index is used later to
220
	// access the operation.
221
	// * @throws IllegalAccessException, {@link InstantiationException} Either
222
	// exception maybe thrown when
223
	// * trying to instance the geometry operation class.
224
	// */
225
	// private int registerGeometryOperation(String geomOpName, Class
226
	// geomOpClass,
227
	// GeometryType geomType)
228
	// throws IllegalAccessException, InstantiationException {
229
	//
230
	// GeometryOperation geomOp = (GeometryOperation) geomOpClass.newInstance();
231
	// return registerGeometryOperation(geomOpName, geomOp, geomType);
232
	// }
213 233

  
214
	/**
215
	 * Registers a GeometryOperation associated to a GeometryType.
216
	 * Returns an unique index that is used later to identify and invoke the operation.<br>
217
	 *
218
	 * By convention, the return value should be stored in a public constant within the class implementing
219
	 * the operation:<BR>
220
	 * <pre>
221
	 * public class MyOperation extends GeometryOperation {
222
	 *   public static final int CODE =
223
	 *     GeometryManager.getInstance()
224
	 *        .registerGeometryOperation("MyOperation", MyOperation.class, myGeomType);
225
	 * }
226
	 * </pre>
227
	 *
228
	 * @param geomOpName Operation's unique name
229
	 * @param geomOpClass GeometryOperation class
230
	 * @param geomType GeometryType instance to which this operation should be associated
231
	 * @return Index assigned to this operation. This index is used later to access the operation.
232
	 * @throws IllegalAccessException, {@link InstantiationException} Either exception maybe thrown when
233
	 * trying to instance the geometry operation class.
234
	 */
235
	private int registerGeometryOperation(String geomOpName, Class geomOpClass,
236
			GeometryType geomType)
237
	throws IllegalAccessException, InstantiationException {
238

  
239
		GeometryOperation geomOp = (GeometryOperation) geomOpClass.newInstance();
240
		return registerGeometryOperation(geomOpName, geomOp, geomType);
241
	}
242

  
243 234
	/* (non-Javadoc)
244 235
	 * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperation, int, int)
245 236
	 */
......
262 253
			if ((type == geometryType.getType())) {
263 254
				code = registerGeometryOperation(geomOpName, geomOp, geometryType);
264 255
			}
265
			{
266
			}
267 256
		}
268 257
		return code;
269 258
	}
......
281 270
			if ((subType == geometryType.getSubType())) {
282 271
				code = registerGeometryOperation(geomOpName, geomOp, geometryType);
283 272
			}
284
			{
285
			}
286 273
		}
287 274
		return code;
288 275
	}
......
344 331
		}
345 332

  
346 333
		// Check if it is registered
347
		GeometryType geomType = (GeometryType) geometryTypeName.get(geomClass
348
				.getName());
349

  
350
		// If it is not, register it
351
		if (geomType == null) {
352
			geomType = new DefaultGeometryType(geomClass, name, id, type, subType);
334
		GeometryType geomType = null;
335
		if (type >= geometryTypes.length || subType >= geometryTypes[0].length
336
				|| (geomType = geometryTypes[type][subType]) == null) {
337
			geomType =
338
					new DefaultGeometryType(geomClass, name, id, type, subType);
339
			registerGeometryType(geomType);
353 340
			geometryTypeName.put(geomClass.getName(), geomType);
354
			geometryTypeList.add(id, geomType);
355
			Map subTypes = null;
356
			Integer key = new Integer(type);
357
			if (!geometrySubtypes.containsKey(key)){
358
				subTypes = new HashMap();
359
				geometrySubtypes.put(key, subTypes);
360
			}else{
361
				subTypes = (HashMap)geometrySubtypes.get(key);
362
			}
363
			subTypes.put(new Integer(subType), geomType);
364
		} else {
365
			// If it is already registered, throw exception
366
			geometryTypeIndex--;
367
			//throw new IllegalArgumentException("Attempt to register a geometry type that is already registered: " + geomClass.getName());
368 341
		}
369
		logger.debug("Class " + geomClass + " registered with name " + geomType.getName());
370 342

  
343
		logger.debug("Class {} registered with name {}", geomClass,
344
				geomType.getName());
345

  
371 346
		return geomType;
372 347
	}
373 348

  
349
	private void registerGeometryType(GeometryType geometryType) {
350
		if (geometryType.getType() >= geometryTypes.length
351
				|| geometryType.getSubType() >= geometryTypes[0].length) {
352

  
353
			// Recreate the geometry type matrix if the types
354
			// or subtypes don't fit
355
			int newTypesSize =
356
					geometryType.getType() < geometryTypes.length ? geometryTypes.length
357
							: geometryType.getType() + 1;
358
			int newSubTypesSize =
359
					geometryType.getSubType() < geometryTypes[0].length ? geometryTypes[0].length
360
							: geometryType.getSubType() + 1;
361
			GeometryType[][] newMatrix =
362
					new GeometryType[newTypesSize][newSubTypesSize];
363

  
364
			for (int i = 0; i < geometryTypes.length; i++) {
365
				System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0,
366
						geometryTypes[i].length);
367
			}
368
			geometryTypes = newMatrix;
369
		}
370

  
371
		geometryTypes[geometryType.getType()][geometryType.getSubType()] =
372
				geometryType;
373
	}
374

  
374 375
	/*
375 376
	 * (non-Javadoc)
376 377
	 * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryType(java.lang.Class, int)
......
379 380
		return registerGeometryType(geomClass, null, type, subType);
380 381
	}
381 382

  
382
	/**
383
	 * Returns an instance of GeometryType given the associated Geometry implementation
384
	 * class.
385
	 *
386
	 * @param geomClass
387
	 * @return Instance of GeometryType associated to the Geometry implementation class
388
	 */
389
	private GeometryType getGeometryType(Class geomClass) {
390
		logger.debug("getting " + geomClass.getName());
391
		return (GeometryType) geometryTypeName.get(geomClass.getName());
392
	}
383
	// /**
384
	// * Returns an instance of GeometryType given the associated Geometry
385
	// implementation
386
	// * class.
387
	// *
388
	// * @param geomClass
389
	// * @return Instance of GeometryType associated to the Geometry
390
	// implementation class
391
	// */
392
	// private GeometryType getGeometryType(Class geomClass) {
393
	// logger.debug("getting " + geomClass.getName());
394
	// return (GeometryType) geometryTypeName.get(geomClass.getName());
395
	// }
393 396

  
394 397
	/*
395 398
	 * (non-Javadoc)
......
406 409
	 * @see org.gvsig.fmap.geom.GeometryManager#getGeometryType(int, int)
407 410
	 */
408 411
	public GeometryType getGeometryType(int type, int subType) throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
409
		Iterator it = geometryTypeName.keySet().iterator();
410
		while (it.hasNext()){
411
			String className = (String)it.next();
412
			GeometryType geometryType = getGeometryType(className);
413
			if ((type == geometryType.getType()) &&
414
					(subType == geometryType.getSubType())){
415
				return geometryType;
416
			}
417
			if (subType == SUBTYPES.UNKNOWN){
418
				throw new GeometryTypeNotValidException(type, subType);
419
			}
412
		GeometryType gType = null;
413
		if (type >= geometryTypes.length || subType >= geometryTypes[0].length) {
414
			throw new GeometryTypeNotValidException(type, subType);
420 415
		}
421
		throw new GeometryTypeNotSupportedException(type, subType);
416

  
417
		gType = geometryTypes[type][subType];
418

  
419
		if (gType == null) {
420
			throw new GeometryTypeNotSupportedException(type, subType);
421
		}
422

  
423
		return gType;
424

  
425
		// Iterator it = geometryTypeName.keySet().iterator();
426
		// while (it.hasNext()){
427
		// String className = (String)it.next();
428
		// GeometryType geometryType = getGeometryType(className);
429
		// if ((type == geometryType.getType()) &&
430
		// (subType == geometryType.getSubType())){
431
		// return geometryType;
432
		// }
433
		// if (subType == SUBTYPES.UNKNOWN){
434
		// throw new GeometryTypeNotValidException(type, subType);
435
		// }
436
		// }
437
		// throw new GeometryTypeNotSupportedException(type, subType);
422 438
	}
423 439

  
424 440
	/*
......
444 460
	 * (non-Javadoc)
445 461
	 * @see org.gvsig.fmap.geom.GeometryManager#create(int)
446 462
	 */
447
	public Geometry create(int type, int subType) throws CreateGeometryException{
448
		if (!geometrySubtypes.containsKey(new Integer(type))){
449
			throw new IllegalArgumentException("geometry type" + type + " has not been registered yet.");
463
	public Geometry create(int type, int subType)
464
			throws CreateGeometryException {
465
		try {
466
			return getGeometryType(type, subType).create();
467
		} catch (GeometryException e) {
468
			throw new CreateGeometryException(type, subType, e);
450 469
		}
451
		Map subtypes = (Map)geometrySubtypes.get(new Integer(type));
452
		if (!subtypes.containsKey(new Integer(subType))){
453
			throw new IllegalArgumentException("geometry subtype" + subType + " has not been registered yet.");
454
		}
455
		return ((GeometryType)subtypes.get(new Integer(subType))).create();
456 470
	}
457 471

  
458 472

  
......
460 474
	 * @see org.gvsig.fmap.geom.GeometryManager#createCurve(org.gvsig.fmap.geom.primitive.GeneralPathX, int)
461 475
	 */
462 476
	public Curve createCurve(GeneralPathX generalPathX, int subType)
463
	throws CreateGeometryException {
477
			throws CreateGeometryException {
464 478
		Curve curve = (Curve)create(TYPES.CURVE, subType);
465 479
		curve.setGeneralPath(generalPathX);
466 480
		return curve;
......
470 484
	 * @see org.gvsig.fmap.geom.GeometryManager#createNullGeometry(int)
471 485
	 */
472 486
	public NullGeometry createNullGeometry(int subType)
473
	throws CreateGeometryException {
487
			throws CreateGeometryException {
474 488
		NullGeometry nullGeom = (NullGeometry)create(TYPES.NULL, subType);
475 489
		return nullGeom;
476 490
	}
......
479 493
	 * @see org.gvsig.fmap.geom.GeometryManager#createPoint(double, double, int)
480 494
	 */
481 495
	public Point createPoint(double x, double y, int subType)
482
	throws CreateGeometryException {
496
			throws CreateGeometryException {
483 497
		Point point = (Point)create(TYPES.POINT, subType);
484 498
		point.setX(x);
485 499
		point.setY(y);
......
490 504
	 * @see org.gvsig.fmap.geom.GeometryManager#createSurface(org.gvsig.fmap.geom.primitive.GeneralPathX, int)
491 505
	 */
492 506
	public Surface createSurface(GeneralPathX generalPathX, int subType)
493
	throws CreateGeometryException {
507
			throws CreateGeometryException {
494 508
		Surface surface = (Surface)create(TYPES.SURFACE, subType);
495 509
		surface.setGeneralPath(generalPathX);
496 510
		return surface;
......
599 613
	 */
600 614
	public Envelope createEnvelope(double minX, double minY, double maxX,
601 615
			double maxY, int subType) throws CreateEnvelopeException {
602
		Envelope envelope = null;
603 616
		org.gvsig.fmap.geom.primitive.Point min = null;
604 617
		org.gvsig.fmap.geom.primitive.Point max = null;
605 618
		try {
606
			min = (org.gvsig.fmap.geom.primitive.Point)create(TYPES.POINT, subType);
619
			GeometryType gType = getGeometryType(TYPES.POINT, subType);
620
			min = (Point) gType.create();
607 621
			min.setX(minX);
608 622
			min.setY(minY);
609
			max = (org.gvsig.fmap.geom.primitive.Point)create(TYPES.POINT, subType);
623
			max = (Point) gType.create();
610 624
			max.setX(maxX);
611 625
			max.setY(maxY);
612
		}catch (CreateGeometryException e){
626
			// min = createPoint(minX, minY, subType);
627
			// max = createPoint(maxX, maxY, subType);
628
		} catch (CreateGeometryException e) {
613 629
			throw new CreateEnvelopeException(subType, e);
630
		} catch (GeometryTypeNotSupportedException e) {
631
			throw new CreateEnvelopeException(subType, e);
632
		} catch (GeometryTypeNotValidException e) {
633
			throw new CreateEnvelopeException(subType, e);
614 634
		}
615
		envelope = createEnvelope(subType);
616
		envelope.setLowerCorner(min);
617
		envelope.setUpperCorner(max);
618
		return envelope;
635
		switch (subType) {
636
		case SUBTYPES.GEOM2D:
637
		case SUBTYPES.GEOM2DM:
638
			// Small optimization to directly create an Envelope2D
639
			// return new Envelope2D(minX, minY, maxX, maxY);
640
			return new Envelope2D(min, max);
641
		default:
642
			Envelope envelope = createEnvelope(subType);
643
			envelope.setLowerCorner(min);
644
			envelope.setUpperCorner(max);
645
			return envelope;
646
		}
619 647
	}
620 648

  
621 649
	public MultiCurve createMultiCurve(GeneralPathX generalPathX, int subType)
......
690 718
	}
691 719

  
692 720
	public MultiSurface createMultiSurface(GeneralPathX generalPathX,
693
			int subType)
694
			throws CreateGeometryException {
721
			int subType) throws CreateGeometryException {
695 722
		if (subType != SUBTYPES.GEOM2D) {
696 723
			// FIXME Exception
697 724
			throw new UnsupportedOperationException();
......
779 806
	 * @see org.gvsig.fmap.geom.GeometryManager#getGeometryOperationNames()
780 807
	 */
781 808
	public List getGeometryOperationNames() {
782
		ArrayList operations = new ArrayList();
809
		List operations = new ArrayList();
783 810
		for (int i=0 ; i<operations.size() ; i++){
784 811
			operations.add(geometryOperations.get(i));
785 812
		}
......
801 828
	public void setFlatness(double flatness) {
802 829
		this.flatness = flatness;
803 830
	}	
804
}
805

  
831
}

Also available in: Unified diff