| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
package org.locationtech.jts.io.gml2; |
| 13 |
|
| 14 |
import java.util.HashMap; |
| 15 |
import java.util.List; |
| 16 |
import java.util.WeakHashMap; |
| 17 |
import java.util.regex.Matcher; |
| 18 |
import java.util.regex.Pattern; |
| 19 |
|
| 20 |
import org.locationtech.jts.geom.Coordinate; |
| 21 |
import org.locationtech.jts.geom.CoordinateSequence; |
| 22 |
import org.locationtech.jts.geom.Envelope; |
| 23 |
import org.locationtech.jts.geom.Geometry; |
| 24 |
import org.locationtech.jts.geom.GeometryCollection; |
| 25 |
import org.locationtech.jts.geom.GeometryFactory; |
| 26 |
import org.locationtech.jts.geom.LineString; |
| 27 |
import org.locationtech.jts.geom.LinearRing; |
| 28 |
import org.locationtech.jts.geom.MultiLineString; |
| 29 |
import org.locationtech.jts.geom.MultiPoint; |
| 30 |
import org.locationtech.jts.geom.MultiPolygon; |
| 31 |
import org.locationtech.jts.geom.Point; |
| 32 |
import org.locationtech.jts.geom.Polygon; |
| 33 |
import org.locationtech.jts.io.gml2.GMLHandler.Handler; |
| 34 |
import org.locationtech.jts.util.StringUtil; |
| 35 |
import org.xml.sax.Attributes; |
| 36 |
import org.xml.sax.SAXException; |
| 37 |
|
| 38 |
|
| 39 |
/** |
| 40 |
* Container for GML2 Geometry parsing strategies which can be represented in JTS. |
| 41 |
* |
| 42 |
* @author David Zwiers, Vivid Solutions. |
| 43 |
*/ |
| 44 |
public class GeometryStrategies{ |
| 45 |
|
| 46 |
/** |
| 47 |
* This set of strategies is not expected to be used directly outside of this distribution. |
| 48 |
* |
| 49 |
* The implementation of this class are intended to be used as static function points in C. These strategies should be associated with an element when the element begins. The strategy is utilized at the end of the element to create an object of value to the user. |
| 50 |
* |
| 51 |
* In this case all the objects are either java.lang.* or JTS Geometry objects |
| 52 |
* |
| 53 |
* @author David Zwiers, Vivid Solutions. |
| 54 |
*/ |
| 55 |
static interface ParseStrategy{ |
| 56 |
/** |
| 57 |
* @param arg Value to interpret |
| 58 |
* @param gf GeometryFactory |
| 59 |
* @return The interpreted value |
| 60 |
* @throws SAXException |
| 61 |
*/ |
| 62 |
Object parse(Handler arg, GeometryFactory gf) throws SAXException; |
| 63 |
} |
| 64 |
|
| 65 |
private static HashMap strategies = loadStrategies(); |
| 66 |
private static HashMap loadStrategies(){ |
| 67 |
HashMap strats = new HashMap(); |
| 68 |
|
| 69 |
|
| 70 |
strats.put(GMLConstants.GML_POINT.toLowerCase(),new ParseStrategy(){ |
| 71 |
|
| 72 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 73 |
|
| 74 |
|
| 75 |
|
| 76 |
if(arg.children.size()!=1) |
| 77 |
throw new SAXException("Cannot create a point without exactly one coordinate"); |
| 78 |
|
| 79 |
int srid = getSrid(arg.attrs,gf.getSRID()); |
| 80 |
|
| 81 |
Object c = arg.children.get(0); |
| 82 |
Point p = null; |
| 83 |
if(c instanceof Coordinate){ |
| 84 |
p = gf.createPoint((Coordinate)c); |
| 85 |
}else{ |
| 86 |
p = gf.createPoint((CoordinateSequence)c); |
| 87 |
} |
| 88 |
if(p.getSRID()!=srid) |
| 89 |
p.setSRID(srid); |
| 90 |
|
| 91 |
return p; |
| 92 |
} |
| 93 |
}); |
| 94 |
|
| 95 |
|
| 96 |
strats.put(GMLConstants.GML_LINESTRING.toLowerCase(),new ParseStrategy(){ |
| 97 |
|
| 98 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 99 |
|
| 100 |
|
| 101 |
|
| 102 |
if(arg.children.size()<1) |
| 103 |
throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence"); |
| 104 |
|
| 105 |
int srid = getSrid(arg.attrs,gf.getSRID()); |
| 106 |
|
| 107 |
LineString ls = null; |
| 108 |
if(arg.children.size() == 1){ |
| 109 |
|
| 110 |
try{ |
| 111 |
CoordinateSequence cs = (CoordinateSequence) arg.children.get(0); |
| 112 |
ls = gf.createLineString(cs); |
| 113 |
}catch(ClassCastException e){ |
| 114 |
throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence",e); |
| 115 |
} |
| 116 |
}else{ |
| 117 |
try{ |
| 118 |
Coordinate[] coords = (Coordinate[]) arg.children.toArray(new Coordinate[arg.children.size()]); |
| 119 |
ls = gf.createLineString(coords); |
| 120 |
}catch(ClassCastException e){ |
| 121 |
throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence",e); |
| 122 |
} |
| 123 |
} |
| 124 |
|
| 125 |
if(ls.getSRID()!=srid) |
| 126 |
ls.setSRID(srid); |
| 127 |
|
| 128 |
return ls; |
| 129 |
} |
| 130 |
}); |
| 131 |
|
| 132 |
|
| 133 |
strats.put(GMLConstants.GML_LINEARRING.toLowerCase(),new ParseStrategy(){ |
| 134 |
|
| 135 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 136 |
|
| 137 |
|
| 138 |
|
| 139 |
if(arg.children.size()!=1 && arg.children.size()<4) |
| 140 |
throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence"); |
| 141 |
|
| 142 |
int srid = getSrid(arg.attrs,gf.getSRID()); |
| 143 |
|
| 144 |
LinearRing ls = null; |
| 145 |
if(arg.children.size() == 1){ |
| 146 |
|
| 147 |
try{ |
| 148 |
CoordinateSequence cs = (CoordinateSequence) arg.children.get(0); |
| 149 |
ls = gf.createLinearRing(cs); |
| 150 |
}catch(ClassCastException e){ |
| 151 |
throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence",e); |
| 152 |
} |
| 153 |
}else{ |
| 154 |
try{ |
| 155 |
Coordinate[] coords = (Coordinate[]) arg.children.toArray(new Coordinate[arg.children.size()]); |
| 156 |
ls = gf.createLinearRing(coords); |
| 157 |
}catch(ClassCastException e){ |
| 158 |
throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence",e); |
| 159 |
} |
| 160 |
} |
| 161 |
|
| 162 |
if(ls.getSRID()!=srid) |
| 163 |
ls.setSRID(srid); |
| 164 |
|
| 165 |
return ls; |
| 166 |
} |
| 167 |
}); |
| 168 |
|
| 169 |
|
| 170 |
strats.put(GMLConstants.GML_POLYGON.toLowerCase(),new ParseStrategy(){ |
| 171 |
|
| 172 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 173 |
|
| 174 |
|
| 175 |
|
| 176 |
if(arg.children.size()<1) |
| 177 |
throw new SAXException("Cannot create a polygon without atleast one linear ring"); |
| 178 |
|
| 179 |
int srid = getSrid(arg.attrs,gf.getSRID()); |
| 180 |
|
| 181 |
LinearRing outer = (LinearRing) arg.children.get(0); |
| 182 |
List t = arg.children.size()>1?arg.children.subList(1,arg.children.size()):null; |
| 183 |
LinearRing[] inner = t==null?null:(LinearRing[]) t.toArray(new LinearRing[t.size()]); |
| 184 |
|
| 185 |
Polygon p = gf.createPolygon(outer,inner); |
| 186 |
|
| 187 |
if(p.getSRID()!=srid) |
| 188 |
p.setSRID(srid); |
| 189 |
|
| 190 |
return p; |
| 191 |
} |
| 192 |
}); |
| 193 |
|
| 194 |
|
| 195 |
strats.put(GMLConstants.GML_BOX.toLowerCase(),new ParseStrategy(){ |
| 196 |
|
| 197 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 198 |
|
| 199 |
|
| 200 |
|
| 201 |
if(arg.children.size()<1 || arg.children.size()>2) |
| 202 |
throw new SAXException("Cannot create a box without either two coords or one coordinate sequence"); |
| 203 |
|
| 204 |
|
| 205 |
|
| 206 |
Envelope box = null; |
| 207 |
if(arg.children.size() == 1){ |
| 208 |
CoordinateSequence cs = (CoordinateSequence) arg.children.get(0); |
| 209 |
box = cs.expandEnvelope(new Envelope()); |
| 210 |
}else{ |
| 211 |
box = new Envelope((Coordinate)arg.children.get(0),(Coordinate)arg.children.get(1)); |
| 212 |
} |
| 213 |
|
| 214 |
return box; |
| 215 |
} |
| 216 |
}); |
| 217 |
|
| 218 |
|
| 219 |
strats.put(GMLConstants.GML_MULTI_POINT.toLowerCase(),new ParseStrategy(){ |
| 220 |
|
| 221 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 222 |
|
| 223 |
|
| 224 |
|
| 225 |
if(arg.children.size()<1) |
| 226 |
throw new SAXException("Cannot create a multi-point without atleast one point"); |
| 227 |
|
| 228 |
int srid = getSrid(arg.attrs,gf.getSRID()); |
| 229 |
|
| 230 |
Point[] pts = (Point[]) arg.children.toArray(new Point[arg.children.size()]); |
| 231 |
|
| 232 |
MultiPoint mp = gf.createMultiPoint(pts); |
| 233 |
|
| 234 |
if(mp.getSRID()!=srid) |
| 235 |
mp.setSRID(srid); |
| 236 |
|
| 237 |
return mp; |
| 238 |
} |
| 239 |
}); |
| 240 |
|
| 241 |
|
| 242 |
strats.put(GMLConstants.GML_MULTI_LINESTRING.toLowerCase(),new ParseStrategy(){ |
| 243 |
|
| 244 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 245 |
|
| 246 |
|
| 247 |
|
| 248 |
if(arg.children.size()<1) |
| 249 |
throw new SAXException("Cannot create a multi-linestring without atleast one linestring"); |
| 250 |
|
| 251 |
int srid = getSrid(arg.attrs,gf.getSRID()); |
| 252 |
|
| 253 |
LineString[] lns = (LineString[]) arg.children.toArray(new LineString[arg.children.size()]); |
| 254 |
|
| 255 |
MultiLineString mp = gf.createMultiLineString(lns); |
| 256 |
|
| 257 |
if(mp.getSRID()!=srid) |
| 258 |
mp.setSRID(srid); |
| 259 |
|
| 260 |
return mp; |
| 261 |
} |
| 262 |
}); |
| 263 |
|
| 264 |
|
| 265 |
strats.put(GMLConstants.GML_MULTI_POLYGON.toLowerCase(),new ParseStrategy(){ |
| 266 |
|
| 267 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 268 |
|
| 269 |
|
| 270 |
|
| 271 |
if(arg.children.size()<1) |
| 272 |
throw new SAXException("Cannot create a multi-polygon without atleast one polygon"); |
| 273 |
|
| 274 |
int srid = getSrid(arg.attrs,gf.getSRID()); |
| 275 |
|
| 276 |
Polygon[] plys = (Polygon[]) arg.children.toArray(new Polygon[arg.children.size()]); |
| 277 |
|
| 278 |
MultiPolygon mp = gf.createMultiPolygon(plys); |
| 279 |
|
| 280 |
if(mp.getSRID()!=srid) |
| 281 |
mp.setSRID(srid); |
| 282 |
|
| 283 |
return mp; |
| 284 |
} |
| 285 |
}); |
| 286 |
|
| 287 |
|
| 288 |
strats.put(GMLConstants.GML_MULTI_GEOMETRY.toLowerCase(),new ParseStrategy(){ |
| 289 |
|
| 290 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 291 |
|
| 292 |
|
| 293 |
|
| 294 |
if(arg.children.size()<1) |
| 295 |
throw new SAXException("Cannot create a multi-polygon without atleast one geometry"); |
| 296 |
|
| 297 |
Geometry[] geoms = (Geometry[]) arg.children.toArray(new Geometry[arg.children.size()]); |
| 298 |
|
| 299 |
GeometryCollection gc = gf.createGeometryCollection(geoms); |
| 300 |
|
| 301 |
return gc; |
| 302 |
} |
| 303 |
}); |
| 304 |
|
| 305 |
|
| 306 |
strats.put(GMLConstants.GML_COORDINATES.toLowerCase(),new ParseStrategy(){ |
| 307 |
|
| 308 |
private WeakHashMap patterns = new WeakHashMap(); |
| 309 |
|
| 310 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 311 |
|
| 312 |
|
| 313 |
|
| 314 |
if(arg.text == null || arg.text.length() == 0) |
| 315 |
throw new SAXException("Cannot create a coordinate sequence without text to parse"); |
| 316 |
|
| 317 |
String decimal = "."; |
| 318 |
String coordSeperator = ","; |
| 319 |
String toupleSeperator = " "; |
| 320 |
|
| 321 |
|
| 322 |
if(arg.attrs.getIndex("decimal")>=0) |
| 323 |
decimal = arg.attrs.getValue("decimal"); |
| 324 |
else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"decimal")>=0) |
| 325 |
decimal = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"decimal"); |
| 326 |
|
| 327 |
if(arg.attrs.getIndex("cs")>=0) |
| 328 |
coordSeperator = arg.attrs.getValue("cs"); |
| 329 |
else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"cs")>=0) |
| 330 |
coordSeperator = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"cs"); |
| 331 |
|
| 332 |
if(arg.attrs.getIndex("ts")>=0) |
| 333 |
toupleSeperator = arg.attrs.getValue("ts"); |
| 334 |
else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"ts")>=0) |
| 335 |
toupleSeperator = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"ts"); |
| 336 |
|
| 337 |
|
| 338 |
String t = arg.text.toString(); |
| 339 |
t = t.replaceAll("\\s"," "); |
| 340 |
/** |
| 341 |
* Remove spaces after commas, for when they are used as separators (default). |
| 342 |
* This prevents coordinates being split by the tuple separator |
| 343 |
*/ |
| 344 |
t = t.replaceAll("\\s*,\\s*", ","); |
| 345 |
|
| 346 |
Pattern ptn = (Pattern) patterns.get(toupleSeperator); |
| 347 |
if(ptn == null){ |
| 348 |
String ts = new String(toupleSeperator); |
| 349 |
if(ts.indexOf('\\')>-1){ |
| 350 |
|
| 351 |
ts = ts.replaceAll("\\\\","\\\\\\\\"); |
| 352 |
} |
| 353 |
if(ts.indexOf('.')>-1){ |
| 354 |
|
| 355 |
ts = ts.replaceAll("\\.","\\\\."); |
| 356 |
} |
| 357 |
ptn = Pattern.compile(ts); |
| 358 |
patterns.put(toupleSeperator,ptn); |
| 359 |
} |
| 360 |
String[] touples = ptn.split(t.trim()); |
| 361 |
|
| 362 |
if(touples.length == 0) |
| 363 |
throw new SAXException("Cannot create a coordinate sequence without a touple to parse"); |
| 364 |
|
| 365 |
|
| 366 |
int numNonNullTouples = 0; |
| 367 |
for(int i=0;i<touples.length;i++){ |
| 368 |
if(touples[i] !=null && !"".equals(touples[i].trim())){ |
| 369 |
if(i!=numNonNullTouples){ |
| 370 |
touples[numNonNullTouples] = touples[i]; |
| 371 |
} |
| 372 |
numNonNullTouples++; |
| 373 |
} |
| 374 |
} |
| 375 |
for(int i=numNonNullTouples;i<touples.length;i++) |
| 376 |
touples[i] = null; |
| 377 |
|
| 378 |
|
| 379 |
if(numNonNullTouples == 0) |
| 380 |
throw new SAXException("Cannot create a coordinate sequence without a non-null touple to parse"); |
| 381 |
|
| 382 |
int dim = StringUtil.split(touples[0], coordSeperator).length; |
| 383 |
CoordinateSequence cs = gf.getCoordinateSequenceFactory().create(numNonNullTouples,dim); |
| 384 |
dim = cs.getDimension(); |
| 385 |
|
| 386 |
boolean replaceDec = !".".equals(decimal); |
| 387 |
|
| 388 |
for(int i=0;i<numNonNullTouples;i++){ |
| 389 |
|
| 390 |
|
| 391 |
ptn = (Pattern) patterns.get(coordSeperator); |
| 392 |
if(ptn == null){ |
| 393 |
String ts = new String(coordSeperator); |
| 394 |
if(ts.indexOf('\\')>-1){ |
| 395 |
|
| 396 |
ts = ts.replaceAll("\\\\","\\\\\\\\"); |
| 397 |
} |
| 398 |
if(ts.indexOf('.')>-1){ |
| 399 |
|
| 400 |
ts = ts.replaceAll("\\.","\\\\."); |
| 401 |
} |
| 402 |
ptn = Pattern.compile(ts); |
| 403 |
patterns.put(coordSeperator,ptn); |
| 404 |
} |
| 405 |
String[] coords = ptn.split(touples[i]); |
| 406 |
|
| 407 |
int dimIndex = 0; |
| 408 |
for(int j=0;j<coords.length && j<dim;j++){ |
| 409 |
if(coords[j] != null && !"".equals(coords[j].trim())){ |
| 410 |
double ordinate = Double.parseDouble(replaceDec?coords[j].replaceAll(decimal,"."):coords[j]); |
| 411 |
cs.setOrdinate(i,dimIndex++,ordinate); |
| 412 |
} |
| 413 |
} |
| 414 |
|
| 415 |
for(;dimIndex<dim;)cs.setOrdinate(i,dimIndex++,Double.NaN); |
| 416 |
} |
| 417 |
|
| 418 |
return cs; |
| 419 |
} |
| 420 |
}); |
| 421 |
|
| 422 |
|
| 423 |
strats.put(GMLConstants.GML_COORD.toLowerCase(),new ParseStrategy(){ |
| 424 |
|
| 425 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 426 |
|
| 427 |
|
| 428 |
|
| 429 |
if(arg.children.size()<1) |
| 430 |
throw new SAXException("Cannot create a coordinate without atleast one axis"); |
| 431 |
if(arg.children.size()>3) |
| 432 |
throw new SAXException("Cannot create a coordinate with more than 3 axis"); |
| 433 |
|
| 434 |
Double[] axis = (Double[]) arg.children.toArray(new Double[arg.children.size()]); |
| 435 |
Coordinate c = new Coordinate(); |
| 436 |
c.x = axis[0].doubleValue(); |
| 437 |
if(axis.length>1) |
| 438 |
c.y = axis[1].doubleValue(); |
| 439 |
if(axis.length>2) |
| 440 |
c.setZ(axis[2].doubleValue()); |
| 441 |
|
| 442 |
return c; |
| 443 |
} |
| 444 |
}); |
| 445 |
|
| 446 |
ParseStrategy coord_child = new ParseStrategy(){ |
| 447 |
|
| 448 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 449 |
if(arg.text == null) |
| 450 |
return null; |
| 451 |
return Double.valueOf((arg.text.toString())); |
| 452 |
} |
| 453 |
}; |
| 454 |
|
| 455 |
|
| 456 |
strats.put(GMLConstants.GML_COORD_X.toLowerCase(),coord_child); |
| 457 |
|
| 458 |
|
| 459 |
strats.put(GMLConstants.GML_COORD_Y.toLowerCase(),coord_child); |
| 460 |
|
| 461 |
|
| 462 |
strats.put(GMLConstants.GML_COORD_Z.toLowerCase(),coord_child); |
| 463 |
|
| 464 |
ParseStrategy member = new ParseStrategy(){ |
| 465 |
|
| 466 |
public Object parse(Handler arg, GeometryFactory gf) throws SAXException { |
| 467 |
if(arg.children.size()!=1) |
| 468 |
throw new SAXException("Geometry Members may only contain one geometry."); |
| 469 |
|
| 470 |
|
| 471 |
|
| 472 |
|
| 473 |
return arg.children.get(0); |
| 474 |
} |
| 475 |
}; |
| 476 |
|
| 477 |
strats.put(GMLConstants.GML_OUTER_BOUNDARY_IS.toLowerCase(),member); |
| 478 |
|
| 479 |
|
| 480 |
strats.put(GMLConstants.GML_INNER_BOUNDARY_IS.toLowerCase(),member); |
| 481 |
|
| 482 |
|
| 483 |
strats.put(GMLConstants.GML_POINT_MEMBER.toLowerCase(),member); |
| 484 |
|
| 485 |
|
| 486 |
strats.put(GMLConstants.GML_LINESTRING_MEMBER.toLowerCase(),member); |
| 487 |
|
| 488 |
|
| 489 |
strats.put(GMLConstants.GML_POLYGON_MEMBER.toLowerCase(),member); |
| 490 |
|
| 491 |
return strats; |
| 492 |
} |
| 493 |
|
| 494 |
|
| 495 |
static int getSrid(Attributes attrs, int defaultValue){ |
| 496 |
String srs = null; |
| 497 |
if(attrs.getIndex(GMLConstants.GML_ATTR_SRSNAME)>=0) |
| 498 |
srs = attrs.getValue(GMLConstants.GML_ATTR_SRSNAME); |
| 499 |
else if(attrs.getIndex(GMLConstants.GML_NAMESPACE,GMLConstants.GML_ATTR_SRSNAME)>=0) |
| 500 |
srs = attrs.getValue(GMLConstants.GML_NAMESPACE,GMLConstants.GML_ATTR_SRSNAME); |
| 501 |
|
| 502 |
if(srs != null){ |
| 503 |
srs = srs.trim(); |
| 504 |
if(srs != null && !"".equals(srs)){ |
| 505 |
try{ |
| 506 |
return Integer.parseInt(srs); |
| 507 |
}catch(NumberFormatException e){ |
| 508 |
String srsNum = extractIntSuffix(srs); |
| 509 |
if (srsNum != null) { |
| 510 |
try{ |
| 511 |
return Integer.parseInt(srsNum); |
| 512 |
}catch(NumberFormatException e2){ |
| 513 |
|
| 514 |
} |
| 515 |
} |
| 516 |
} |
| 517 |
} |
| 518 |
} |
| 519 |
|
| 520 |
return defaultValue; |
| 521 |
} |
| 522 |
|
| 523 |
static Pattern PATT_SUFFIX_INT = Pattern.compile("(\\d+)$"); |
| 524 |
|
| 525 |
static String extractIntSuffix(String s) { |
| 526 |
Matcher matcher = PATT_SUFFIX_INT.matcher(s); |
| 527 |
if (matcher.find()) { |
| 528 |
return matcher.group(1); |
| 529 |
} |
| 530 |
return null; |
| 531 |
} |
| 532 |
|
| 533 |
/** |
| 534 |
* @param uri Not currently used, included for future work |
| 535 |
* @param localName Used to look up an appropriate parse strategy |
| 536 |
* @return The ParseStrategy which should be employed |
| 537 |
* |
| 538 |
* @see ParseStrategy |
| 539 |
*/ |
| 540 |
public static ParseStrategy findStrategy(String uri,String localName){ |
| 541 |
return localName == null?null:(ParseStrategy) strategies.get(localName.toLowerCase()); |
| 542 |
} |
| 543 |
} |
| 544 |
|