Revision 21731 branches/v2_0_0_prep/libraries/libFMap_geometries/src/org/gvsig/fmap/geom/GeometryManager.java
GeometryManager.java | ||
---|---|---|
56 | 56 |
/** |
57 | 57 |
* This singleton provides a centralized access to gvSIG's Geometry Model. |
58 | 58 |
* Its responsibilities are:<br> |
59 |
*
|
|
59 |
* |
|
60 | 60 |
* <ul> |
61 | 61 |
* <li>Offering a set of convenient methods for registering and retrieving geometry types. |
62 |
* <li>Offering a set of convenient methods for registering and retrieving geometry operations associated
|
|
62 |
* <li>Offering a set of convenient methods for registering and retrieving geometry operations associated |
|
63 | 63 |
* to one or more geometry types. |
64 |
* <li><code>TODO:</code> Offering a set of convenient methods for registering and retrieving custom
|
|
64 |
* <li><code>TODO:</code> Offering a set of convenient methods for registering and retrieving custom |
|
65 | 65 |
* geometry factories. |
66 | 66 |
* <ul> |
67 |
*
|
|
67 |
* |
|
68 | 68 |
* @author jiyarza |
69 | 69 |
* |
70 | 70 |
*/ |
71 | 71 |
public class GeometryManager { |
72 | 72 |
|
73 | 73 |
private static Logger logger = Logger.getLogger(GeometryManager.class); |
74 |
|
|
74 |
|
|
75 | 75 |
private static GeometryManager instance; |
76 | 76 |
|
77 |
/** This list holds the unique name of all registered geometry operations.
|
|
77 |
/** This list holds the unique name of all registered geometry operations. |
|
78 | 78 |
* The index in which they are stored is also the operation code used to invoke each one of them */ |
79 | 79 |
private List geometryOperations = new ArrayList(); |
80 |
|
|
81 |
/** Common operations are registered here. Type specific operations are registered in the corresponding GeometryType instance */
|
|
80 |
|
|
81 |
/** Common operations are registered here. Type specific operations are registered in the corresponding GeometryType instance */ |
|
82 | 82 |
private List commonOperations = new ArrayList(); |
83 |
|
|
84 |
/** Common operations are assigned an index greater or equal than this constant, so that it is easy and efficient for the manager
|
|
83 |
|
|
84 |
/** Common operations are assigned an index greater or equal than this constant, so that it is easy and efficient for the manager |
|
85 | 85 |
* to decide whether to lookup in the common register or in the type specific register. */ |
86 | 86 |
private static final int COMMON_OPS_OFFSET = 1000; |
87 |
|
|
88 |
/** This map holds the instances of all registered GeometryType. The key is the name of the specific Geometry subclass.
|
|
89 |
* In other words, the string "org.gvsig.fmap.geom.primitive.Point2D" is the hash key to obtain an instance of GeometryType holding the
|
|
87 |
|
|
88 |
/** This map holds the instances of all registered GeometryType. The key is the name of the specific Geometry subclass. |
|
89 |
* In other words, the string "org.gvsig.fmap.geom.primitive.Point2D" is the hash key to obtain an instance of GeometryType holding the |
|
90 | 90 |
* operations associated to the class org.gvsig.fmap.geom.primitive.Point2D. |
91 | 91 |
*/ |
92 | 92 |
private Map geometryTypes = new HashMap(); |
93 |
|
|
94 |
/** GeometryType index counter. Each time a new geometry type is registered it is assigned this counter's value as index and after that
|
|
93 |
|
|
94 |
/** GeometryType index counter. Each time a new geometry type is registered it is assigned this counter's value as index and after that |
|
95 | 95 |
* it is incremented by 1 */ |
96 |
private int geomTypeIndex = 10000;
|
|
96 |
private int geomTypeIndex = 65536;//2^16
|
|
97 | 97 |
|
98 | 98 |
/** |
99 | 99 |
* Geometry Factory |
100 | 100 |
*/ |
101 | 101 |
private GeometryFactory factory = new GeometryFactory(); |
102 |
|
|
102 |
|
|
103 | 103 |
/** |
104 | 104 |
* Singleton's private constructor |
105 | 105 |
*/ |
... | ... | |
125 | 125 |
public void registerGeometryFactory(GeometryFactory factory) { |
126 | 126 |
this.factory = factory; |
127 | 127 |
} |
128 |
|
|
128 |
|
|
129 | 129 |
/** |
130 | 130 |
* Returns the current geometry factory |
131 | 131 |
* @return |
... | ... | |
133 | 133 |
public GeometryFactory getGeometryFactory() { |
134 | 134 |
return factory; |
135 | 135 |
} |
136 |
|
|
136 |
|
|
137 | 137 |
/** |
138 |
* Registers the unique name of one operation. If it already exists then this method does nothing but returning
|
|
139 |
* the name's corresponding index.
|
|
138 |
* Registers the unique name of one operation. If it already exists then this method does nothing but returning |
|
139 |
* the name's corresponding index. |
|
140 | 140 |
* @param geomOpName Name used to register the geometry operation |
141 | 141 |
* @return index assigned to the operation name passed as parameter |
142 | 142 |
*/ |
... | ... | |
151 | 151 |
} |
152 | 152 |
return index; |
153 | 153 |
} |
154 |
|
|
155 |
|
|
154 |
|
|
155 |
|
|
156 | 156 |
/** |
157 |
* Sets a common operation into the common operations map.
|
|
157 |
* Sets a common operation into the common operations map. |
|
158 | 158 |
* @param index index in which to set the operation |
159 | 159 |
* @param geomOp operation to be set |
160 | 160 |
*/ |
161 | 161 |
private void setCommonOperation(int index, GeometryOperation geomOp) { |
162 |
|
|
162 |
|
|
163 | 163 |
while (index > commonOperations.size()) { |
164 | 164 |
commonOperations.add(null); |
165 | 165 |
} |
166 |
|
|
166 |
|
|
167 | 167 |
if (index == commonOperations.size()) { |
168 | 168 |
commonOperations.add(geomOp); |
169 |
} else {
|
|
169 |
} else { |
|
170 | 170 |
commonOperations.set(index, geomOp); |
171 | 171 |
} |
172 |
}
|
|
173 |
|
|
172 |
} |
|
173 |
|
|
174 | 174 |
/** |
175 |
* Registers a GeometryOperation associated to a GeometryType.
|
|
175 |
* Registers a GeometryOperation associated to a GeometryType. |
|
176 | 176 |
* Returns an unique index that is used later to identify and invoke the operation. |
177 |
*
|
|
177 |
* |
|
178 | 178 |
* This method is only used if you already got a reference to the GeometryType. If not, |
179 |
* it is more convenient to use the method that receives the geometry class as parameter.
|
|
180 |
*
|
|
181 |
* By convention, the return value should be stored in a public constant within the class implementing
|
|
182 |
* the operation:<BR>
|
|
179 |
* it is more convenient to use the method that receives the geometry class as parameter. |
|
180 |
* |
|
181 |
* By convention, the return value should be stored in a public constant within the class implementing |
|
182 |
* the operation:<BR> |
|
183 | 183 |
* <pre> |
184 | 184 |
* public class MyOperation extends GeometryOperation { |
185 |
* public static final int CODE =
|
|
185 |
* public static final int CODE = |
|
186 | 186 |
* GeometryManager.getInstance() |
187 | 187 |
* .registerGeometryOperation("MyOperation", new MyOperation(), geomType); |
188 | 188 |
* } |
... | ... | |
191 | 191 |
* @param geomOp Specific GeometryOperation's instance implementing this operation |
192 | 192 |
* @param geomType GeometryType instance to which this operation should be associated |
193 | 193 |
* @return Index assigned to this operation. This index is used later to access the operation. |
194 |
*
|
|
194 |
* |
|
195 | 195 |
*/ |
196 | 196 |
public int registerGeometryOperation(String geomOpName, |
197 | 197 |
GeometryOperation geomOp, GeometryType geomType) { |
... | ... | |
201 | 201 |
throw new IllegalArgumentException("geomType cannot be null."); |
202 | 202 |
|
203 | 203 |
int index = registerGeometryOperationName(geomOpName); |
204 |
|
|
204 |
|
|
205 | 205 |
geomType.setGeometryOperation(index, geomOp); |
206 | 206 |
|
207 | 207 |
return index; |
208 | 208 |
} |
209 | 209 |
|
210 | 210 |
/** |
211 |
* Registers a GeometryOperation that is common for all GeometryType (registered yet or not)
|
|
211 |
* Registers a GeometryOperation that is common for all GeometryType (registered yet or not) |
|
212 | 212 |
* Returns an unique index that is used later to identify and invoke the operation. |
213 |
*
|
|
214 |
* By convention, the return value should be stored in a public constant within the class implementing
|
|
215 |
* the operation:<BR>
|
|
213 |
* |
|
214 |
* By convention, the return value should be stored in a public constant within the class implementing |
|
215 |
* the operation:<BR> |
|
216 | 216 |
* <pre> |
217 | 217 |
* public class MyOperation extends GeometryOperation { |
218 |
* public static final int CODE =
|
|
218 |
* public static final int CODE = |
|
219 | 219 |
* GeometryManager.getInstance() |
220 | 220 |
* .registerGeometryOperation("MyOperation", new MyOperation()); |
221 | 221 |
* } |
222 | 222 |
* </pre> |
223 |
*
|
|
223 |
* |
|
224 | 224 |
* @param geomOpName Operation's unique name |
225 | 225 |
* @param geomOp Specific GeometryOperation's instance implementing this operation |
226 |
* @return Index assigned to this operation. This index is used later to access the operation.
|
|
226 |
* @return Index assigned to this operation. This index is used later to access the operation. |
|
227 | 227 |
*/ |
228 | 228 |
public int registerGeometryOperation(String geomOpName, |
229 | 229 |
GeometryOperation geomOp) { |
... | ... | |
235 | 235 |
int index = registerGeometryOperationName(geomOpName); |
236 | 236 |
|
237 | 237 |
setCommonOperation(index, geomOp); |
238 |
|
|
239 |
|
|
238 |
|
|
239 |
|
|
240 | 240 |
return index + COMMON_OPS_OFFSET; |
241 |
|
|
241 |
|
|
242 | 242 |
} |
243 |
|
|
243 |
|
|
244 | 244 |
/** |
245 |
* Registers a GeometryOperation associated to a GeometryType.
|
|
245 |
* Registers a GeometryOperation associated to a GeometryType. |
|
246 | 246 |
* Returns an unique index that is used later to identify and invoke the operation.<br> |
247 |
*
|
|
248 |
* By convention, the return value should be stored in a public constant within the class implementing
|
|
249 |
* the operation:<BR>
|
|
247 |
* |
|
248 |
* By convention, the return value should be stored in a public constant within the class implementing |
|
249 |
* the operation:<BR> |
|
250 | 250 |
* <pre> |
251 | 251 |
* public class MyOperation extends GeometryOperation { |
252 |
* public static final int CODE =
|
|
252 |
* public static final int CODE = |
|
253 | 253 |
* GeometryManager.getInstance() |
254 | 254 |
* .registerGeometryOperation("MyOperation", new MyOperation(), MyGeometry.class); |
255 | 255 |
* } |
256 | 256 |
* </pre> |
257 |
*
|
|
257 |
* |
|
258 | 258 |
* This method is only used if you have not a reference to the GeometryType associated to the |
259 | 259 |
* geometry class. If you have such reference then it is slightly faster to use the method that receives |
260 | 260 |
* the GeometryType.<br> |
261 |
*
|
|
261 |
* |
|
262 | 262 |
* @param geomOpName Operation's unique name |
263 | 263 |
* @param geomOp Specific GeometryOperation's instance implementing this operation |
264 | 264 |
* @param geomClass Geometry implementation class |
265 | 265 |
* @return Index assigned to this operation. This index is used later to access the operation. |
266 |
*/
|
|
266 |
*/ |
|
267 | 267 |
public int registerGeometryOperation(String geomOpName, |
268 | 268 |
GeometryOperation geomOp, Class geomClass) { |
269 |
|
|
269 |
|
|
270 | 270 |
GeometryType geomType = getGeometryType(geomClass); |
271 | 271 |
return registerGeometryOperation(geomOpName, geomOp, geomType); |
272 | 272 |
} |
273 |
|
|
274 | 273 |
|
274 |
|
|
275 | 275 |
/** |
276 |
* Registers a GeometryOperation associated to a GeometryType.
|
|
276 |
* Registers a GeometryOperation associated to a GeometryType. |
|
277 | 277 |
* Returns an unique index that is used later to identify and invoke the operation.<br> |
278 |
*
|
|
279 |
* By convention, the return value should be stored in a public constant within the class implementing
|
|
280 |
* the operation:<BR>
|
|
278 |
* |
|
279 |
* By convention, the return value should be stored in a public constant within the class implementing |
|
280 |
* the operation:<BR> |
|
281 | 281 |
* <pre> |
282 | 282 |
* public class MyOperation extends GeometryOperation { |
283 |
* public static final int CODE =
|
|
283 |
* public static final int CODE = |
|
284 | 284 |
* GeometryManager.getInstance() |
285 | 285 |
* .registerGeometryOperation("MyOperation", MyOperation.class, myGeomType); |
286 | 286 |
* } |
... | ... | |
296 | 296 |
public int registerGeometryOperation(String geomOpName, Class geomOpClass, |
297 | 297 |
GeometryType geomType) |
298 | 298 |
throws IllegalAccessException, InstantiationException { |
299 |
|
|
300 |
GeometryOperation geomOp = (GeometryOperation) geomOpClass.newInstance();
|
|
301 |
return registerGeometryOperation(geomOpName, geomOp, geomType);
|
|
299 |
|
|
300 |
GeometryOperation geomOp = (GeometryOperation) geomOpClass.newInstance(); |
|
301 |
return registerGeometryOperation(geomOpName, geomOp, geomType); |
|
302 | 302 |
} |
303 | 303 |
|
304 | 304 |
/** |
305 |
* Registers a Geometry implementation class as a new geometry type and returns the
|
|
305 |
* Registers a Geometry implementation class as a new geometry type and returns the |
|
306 | 306 |
* associated GeometryType instance. If the class is already registered |
307 | 307 |
* then this method does nothing but returning the associated GeometryType.<br> |
308 |
*
|
|
308 |
* |
|
309 | 309 |
* How to register a new geometry type: |
310 | 310 |
* <pre> |
311 |
*
|
|
311 |
* |
|
312 | 312 |
* public class MyGeom3D implements Solid { |
313 | 313 |
* private static final GeometryType geomType = GeometryManager.getInstance() |
314 | 314 |
* .registerGeometryType(MyGeom3D.class, "MyGeom3D"); |
315 |
*
|
|
315 |
* |
|
316 | 316 |
* public static final int .CODE = geomType.getType(); |
317 | 317 |
* ... |
318 | 318 |
* public int getType() { |
... | ... | |
320 | 320 |
* } |
321 | 321 |
* } |
322 | 322 |
* </pre> |
323 |
*
|
|
323 |
* |
|
324 | 324 |
* @param geomClass |
325 |
* Geometry subclass. It must not be null and must implement Geometry, otherwise an exception
|
|
325 |
* Geometry subclass. It must not be null and must implement Geometry, otherwise an exception |
|
326 | 326 |
* is raised. |
327 | 327 |
* @param name |
328 |
* Symbolic name for the geometry type, it can be null. If it is null then the symbolic name
|
|
328 |
* Symbolic name for the geometry type, it can be null. If it is null then the symbolic name |
|
329 | 329 |
* will be the simple class name. |
330 | 330 |
* @return Instance of GeometryType associated to the Geometry implementation class |
331 | 331 |
* geomClass |
... | ... | |
356 | 356 |
throw new IllegalArgumentException("Attempt to register a geometry type that is already registered: " + geomClass.getName()); |
357 | 357 |
} |
358 | 358 |
logger.debug("Class " + geomType.getGeometryClass().getName() + " registered with name " + geomType.getName()); |
359 |
|
|
359 |
|
|
360 | 360 |
return geomType; |
361 | 361 |
} |
362 | 362 |
|
363 | 363 |
/** |
364 |
* Registers a Geometry implementation as a new geometry type and returns the
|
|
364 |
* Registers a Geometry implementation as a new geometry type and returns the |
|
365 | 365 |
* associated GeometryType instance. If the class is already registered |
366 | 366 |
* then this method does nothing but returning the associated GeometryType.<br> |
367 |
*
|
|
367 |
* |
|
368 | 368 |
* In this case the symbolic name will be the geometry's simple class name |
369 |
*
|
|
369 |
* |
|
370 | 370 |
* How to register a new geometry type: |
371 | 371 |
* <pre> |
372 |
*
|
|
372 |
* |
|
373 | 373 |
* public class MyGeom3D implements Solid { |
374 | 374 |
* private static final GeometryType geomType = GeometryManager.getInstance() |
375 | 375 |
* .registerGeometryType(MyGeom3D.class); |
376 |
*
|
|
376 |
* |
|
377 | 377 |
* public static final int .CODE = geomType.getType(); |
378 | 378 |
* ... |
379 | 379 |
* public int getType() { |
... | ... | |
381 | 381 |
* } |
382 | 382 |
* } |
383 | 383 |
* </pre> |
384 |
*
|
|
384 |
* |
|
385 | 385 |
* @param geomClass |
386 |
* Geometry implementation class. It must not be null and must implement Geometry,
|
|
386 |
* Geometry implementation class. It must not be null and must implement Geometry, |
|
387 | 387 |
* otherwise an exception is thrown. |
388 | 388 |
* @return Instance of GeometryType associated to the Geometry implementation class |
389 | 389 |
* @throws IllegalArgumentException |
... | ... | |
393 | 393 |
return registerGeometryType(geomClass, null); |
394 | 394 |
} |
395 | 395 |
/** |
396 |
* Returns an instance of GeometryType given the associated Geometry implementation
|
|
396 |
* Returns an instance of GeometryType given the associated Geometry implementation |
|
397 | 397 |
* class. |
398 |
*
|
|
398 |
* |
|
399 | 399 |
* @param geomClass |
400 | 400 |
* @return Instance of GeometryType associated to the Geometry implementation class |
401 | 401 |
*/ |
... | ... | |
407 | 407 |
/** |
408 | 408 |
* Returns the associated GeometryType given the fully qualified name of |
409 | 409 |
* the Geometry implementation class. |
410 |
*
|
|
410 |
* |
|
411 | 411 |
* @param className |
412 | 412 |
* Fully qualified name of the Geometry implementation class |
413 | 413 |
* @return GeometryType associated to the class |
... | ... | |
417 | 417 |
} |
418 | 418 |
|
419 | 419 |
/** |
420 |
* Returns an operation given the Geometry implementation class and the operation
|
|
420 |
* Returns an operation given the Geometry implementation class and the operation |
|
421 | 421 |
* code. If opCode corresponds to a common operation (a common operation is an operation |
422 | 422 |
* registered for all geometries), then this method returns the common operation. |
423 | 423 |
* <br> |
424 |
* For better performance, if you need to call an operation multiple times,
|
|
425 |
* use this method only once and keep the returned object in a local variable
|
|
424 |
* For better performance, if you need to call an operation multiple times, |
|
425 |
* use this method only once and keep the returned object in a local variable |
|
426 | 426 |
* over which you can iterate. For instance: |
427 |
*
|
|
427 |
* |
|
428 | 428 |
* <pre> |
429 | 429 |
* ... |
430 | 430 |
* // Get the operation you need |
... | ... | |
437 | 437 |
* } catch (GeometryOperationNotSupportedException gonse) { |
438 | 438 |
* // treat exception |
439 | 439 |
* } |
440 |
*
|
|
440 |
* |
|
441 | 441 |
* // Fill the operation context with required params |
442 | 442 |
* GeometryOperationContext ctx = new GeometryOperationContext(); |
443 |
*
|
|
444 |
* // Here is the main loop where you call the operation
|
|
443 |
* |
|
444 |
* // Here is the main loop where you call the operation |
|
445 | 445 |
* for (int i=0; i<MyGeometries.length; i++) { |
446 | 446 |
* Object result = geomOp.invoke(myGeometries[i], ctx); |
447 | 447 |
* } |
448 |
*
|
|
448 |
* |
|
449 | 449 |
* </pre> |
450 |
*
|
|
450 |
* |
|
451 | 451 |
* @param geomClass |
452 | 452 |
* @param opCode |
453 | 453 |
* @return Geometry operation |
454 | 454 |
*/ |
455 | 455 |
public GeometryOperation getGeometryOperation(Class geomClass, int opCode) throws GeometryTypeNotSupportedException, GeometryOperationNotSupportedException { |
456 |
|
|
457 |
GeometryOperation geomOp = null;
|
|
458 |
|
|
456 |
|
|
457 |
GeometryOperation geomOp = null; |
|
458 |
|
|
459 | 459 |
// Check if it is a common operation, and if so, get it from the common registry |
460 | 460 |
if (opCode >= COMMON_OPS_OFFSET) { |
461 | 461 |
geomOp = ((GeometryOperation)commonOperations.get(opCode - COMMON_OPS_OFFSET)); |
462 |
|
|
462 |
|
|
463 | 463 |
if (geomOp == null) { |
464 | 464 |
throw new GeometryOperationNotSupportedException(opCode); |
465 | 465 |
} |
466 | 466 |
} else { |
467 |
// If it is type specific, get it from its type registry
|
|
467 |
// If it is type specific, get it from its type registry |
|
468 | 468 |
if (geomClass != null) { |
469 | 469 |
GeometryType geomType = getGeometryType(geomClass); |
470 |
|
|
470 |
|
|
471 | 471 |
// If the geometry type is not registered, throw an exception |
472 | 472 |
if (geomType == null) { |
473 | 473 |
throw new GeometryTypeNotSupportedException(geomClass); |
474 | 474 |
} |
475 |
|
|
475 |
|
|
476 | 476 |
// Get the operation |
477 | 477 |
geomOp = geomType.getGeometryOperation(opCode); |
478 |
|
|
478 |
|
|
479 | 479 |
// If the operation is not registered throw an exception |
480 | 480 |
if (geomOp == null) { |
481 | 481 |
throw new GeometryOperationNotSupportedException(opCode, geomType); |
482 |
}
|
|
482 |
} |
|
483 | 483 |
} |
484 |
}
|
|
484 |
} |
|
485 | 485 |
return geomOp; |
486 | 486 |
} |
487 |
|
|
487 |
|
|
488 | 488 |
/** |
489 |
* Invokes an operation given its code, the geometry and the operation context holding the
|
|
489 |
* Invokes an operation given its code, the geometry and the operation context holding the |
|
490 | 490 |
* parameters required for the operation. |
491 |
*
|
|
491 |
* |
|
492 | 492 |
* @param opCode Operation code. |
493 | 493 |
* @param geom Geometry to which apply the operation |
494 | 494 |
* @param ctx Context holding the operation parameters |
495 |
* @return The object returned by an operation, depends on each operation.
|
|
495 |
* @return The object returned by an operation, depends on each operation. |
|
496 | 496 |
*/ |
497 | 497 |
public Object invokeOperation(int opCode, Geometry geom, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException { |
498 |
|
|
498 |
|
|
499 | 499 |
GeometryOperation geomOp = null; |
500 |
|
|
500 |
|
|
501 | 501 |
if (opCode < COMMON_OPS_OFFSET) { |
502 | 502 |
geomOp = geom.getGeometryType().getGeometryOperation(opCode); |
503 | 503 |
} else { |
504 | 504 |
geomOp = ((GeometryOperation)commonOperations.get(opCode - COMMON_OPS_OFFSET)); |
505 | 505 |
} |
506 |
|
|
506 |
|
|
507 | 507 |
if (geomOp != null) { |
508 | 508 |
return geomOp.invoke(geom, ctx); |
509 | 509 |
} |
510 |
|
|
510 |
|
|
511 | 511 |
throw new GeometryOperationNotSupportedException(opCode, geom.getGeometryType()); |
512 | 512 |
} |
513 | 513 |
} |
Also available in: Unified diff