1 22 23 28 29 package org.xquark.mapper.dbms; 30 31 import java.net.URL ; 32 import java.util.*; 33 34 import javax.xml.parsers.SAXParserFactory ; 35 36 import org.xml.sax.*; 37 import org.xml.sax.helpers.DefaultHandler ; 38 import org.xquark.mapper.metadata.RepositoryConstants; 39 import org.xquark.schema.validation.*; 40 41 44 public class TableSpecLoader extends DefaultHandler 45 { 46 private static final String RCSRevision = "$Revision: 1.1 $"; 47 private static final String RCSName = "$Name: $"; 48 49 50 56 public static String REPOSITORY_DATA_VERSION; 57 58 62 private final static String SCHEMA_FILENAME = "TableSpec.xsd"; 63 private final static String DATA_FILENAME = "TableSpec.xml"; 64 private final static String ROOT_ELEMENT = "tables"; 65 private final static String VERSION_ATTR = "version"; 66 private final static String TABLE_ELEMENT = "table"; 67 private final static String TYPE_ATTR = "type"; 68 private final static String SUFFIX_ATTR = "suffix"; 69 private final static String SEQ_ATTR = "sequence"; 70 private final static String CAT_ATTR = "cat"; 71 private final static String DBMS_ATTR = "dbms"; 72 private final static String DBMS_TYPE_ATTR = "dbmsType"; 73 74 private final static String COLUMN_ELEMENT = "column"; 75 private final static String NAME_ATTR = "name"; 76 private final static String NULLABLE_ATTR = "nullable"; 77 private final static String KEY_ATTR = "key"; 78 79 private final static String JDBC_TYPE_ELEMENT = "type"; 80 private final static String JDBC_TYPE_ATTR = "jdbc"; 81 private final static String MAX_LEN_ELEMENT = "maxLen"; 82 private final static String PRECISION_ELEMENT = "precision"; 83 private final static String SCALE_ELEMENT = "scale"; 84 private final static String PARAM_ATTR = "param"; 85 86 private final static short ANY_DBMS = 0; 87 88 private final static String CONSTRAINT_ELEMENT = "constraint"; 89 private final static String COLUMNS_ATTR = "columns"; 90 91 private final static String INDEX_ELEMENT = "index"; 92 93 94 private final static short UNKNOWN = 0; 95 private final static short ROOT = 1; 96 private final static short TABLE = 2; 97 private final static short COLUMN = 3; 98 private final static short JDBC_TYPE = 4; 99 private final static short KEY = 5; 100 private final static short NULLABLE = 6; 101 private final static short CONSTRAINT = 7; 102 private final static short INDEX = 8; 103 private final static short MAX_LEN = 9; 104 private final static short PRECISION = 10; 105 private final static short SCALE = 11; 106 107 private static TableSpecLoader singleton; 111 private List[] tables = new List[TableSpec.CAT_COUNT]; private SchemaValidationContext context; 115 private short status = UNKNOWN; 116 private TableSpec wTable; 117 private ColumnSpec wColumn; 118 private List columns = new ArrayList(); 119 private Map columnMap = new HashMap(); 120 private List constraints = new ArrayList(); 121 private List indexes = new ArrayList(); 122 123 static 124 { 125 singleton = new TableSpecLoader(); 126 } 127 128 private TableSpecLoader() 129 { 130 for(int i = 0; i < TableSpec.CAT_COUNT; i++) 131 tables[i] = new ArrayList(); 132 load(); 133 } 134 135 public static TableSpecLoader getInstance() 136 { 137 return singleton; 138 } 139 140 private void load() 141 { 142 URL in = TableSpecLoader.class.getResource(RepositoryConstants.RESOURCES_FOLDER + DATA_FILENAME); 144 if (in == null) 145 throw new RuntimeException ("Resource " + DATA_FILENAME + " couldn't be found."); 146 InputSource resource = new InputSource(in.toString()); 147 XMLReader parser; 148 try 149 { 150 SAXParserFactory factory = SAXParserFactory.newInstance(); 151 factory.setNamespaceAware(true); 152 parser = factory.newSAXParser().getXMLReader(); 153 } 154 catch (Exception e) 155 { 156 throw new RuntimeException ("JAXP exception while intantiating a SAX parser for internal use (" + e.getMessage() + ")."); 157 } 158 159 context = new SchemaValidationContext(); 160 ValidatingSchemaFilter filter = new ValidatingSchemaFilter(parser, context); 161 filter.setContentHandler(this); 162 try 163 { 164 filter.parse(resource); 165 } 166 catch (Exception e) 167 { 168 throw new RuntimeException ("Exception while parsing Repository table specifications (" + e.getMessage() + ")."); 169 } 170 } 172 173 174 public List getTableSpecs(byte cat) 175 { 176 return tables[cat]; 177 } 178 179 180 public List getTableSpecs(byte cat, short vendor) 181 { 182 ArrayList res = new ArrayList(); 183 TableSpec wTable; 184 Iterator it = tables[cat].iterator(); 185 while (it.hasNext()) 186 { 187 wTable = (TableSpec)it.next(); 188 if (wTable.getDBMSVendor() == ANY_DBMS || wTable.getDBMSVendor() == vendor ) 189 res.add(wTable); 190 } 191 return res; 192 } 193 194 195 public TableSpec getTableSpec(byte cat, byte tableType) 196 { 197 TableSpec res = null, wTable; 198 Iterator it = tables[cat].iterator(); 199 while (it.hasNext()) 200 { 201 wTable = (TableSpec)it.next(); 202 if (wTable.getType() == tableType) 203 { 204 res = wTable; 205 break; 206 } 207 } 208 return res; 209 } 210 211 public void startElement(String ns, String local, String qName, Attributes atts) 212 throws SAXException 213 { 214 215 switch (status) 216 { 217 case UNKNOWN: 218 if (local.equals(ROOT_ELEMENT)) 219 status = ROOT; 220 break; 221 case ROOT: 222 if (local.equals(TABLE_ELEMENT)) 223 status = TABLE; 224 break; 225 case TABLE: 226 if (local.equals(COLUMN_ELEMENT)) 227 status = COLUMN; 228 else if (local.equals(CONSTRAINT_ELEMENT)) 229 status = CONSTRAINT; 230 else if (local.equals(INDEX_ELEMENT)) 231 status = INDEX; 232 break; 233 case COLUMN: 234 if (local.equals(JDBC_TYPE_ELEMENT)) 235 status = JDBC_TYPE; 236 break; 237 case JDBC_TYPE: 238 if (local.equals(MAX_LEN_ELEMENT)) 239 status = MAX_LEN; 240 else if (local.equals(PRECISION_ELEMENT)) 241 status = PRECISION; 242 else if (local.equals(SCALE_ELEMENT)) 243 status = SCALE; 244 break; 245 default: 246 } 247 248 249 ElementPSVInfoset infoset = context.getCurrentInfoset(); 250 switch (status) 251 { 252 case ROOT: 253 REPOSITORY_DATA_VERSION = context.getCurrentInfoset().getAttributePSVInfoset(null, VERSION_ATTR).getNormalizedValue(); 254 break; 255 case TABLE: 256 wTable = new TableSpec(); break; 258 case COLUMN: 259 wColumn = new ColumnSpec(); 260 break; 261 default: 262 } 263 264 } 265 266 public void endElement(String ns, String local, String qName) 267 throws SAXException 268 { 269 270 ElementPSVInfoset infoset = context.getCurrentInfoset(); 271 switch (status) 272 { 273 case TABLE: 274 completeTable(infoset); 275 break; 276 277 case COLUMN: 278 completeColumn(infoset); 279 break; 280 281 case JDBC_TYPE: 282 fillColumnType(infoset); 283 break; 284 285 case MAX_LEN: 286 fillSize(infoset); 287 break; 288 289 case PRECISION: 290 fillPrecision(infoset); 291 break; 292 293 case SCALE: 294 fillScale(infoset); 295 break; 296 297 case INDEX: 298 createIndex(infoset); 299 break; 300 301 case CONSTRAINT: 302 createConstraint(infoset); 303 break; 304 default: 305 } 306 307 308 switch (status) 309 { 310 case ROOT: 311 status = UNKNOWN; 312 break; 313 case TABLE: 314 status = ROOT; 315 break; 316 case COLUMN: 317 case INDEX: 318 case CONSTRAINT: 319 status = TABLE; 320 break; 321 case JDBC_TYPE: 322 case KEY: 323 case NULLABLE: 324 status = COLUMN; 325 break; 326 case MAX_LEN: 327 case PRECISION: 328 case SCALE: 329 status = JDBC_TYPE; 330 break; 331 default: 332 } 333 } 334 335 void completeTable(ElementPSVInfoset infoset) 336 { 337 String dbmsType = null; 338 String suffix = null; 339 boolean seq = false; 340 byte cat = -1; 341 short dbms = -1; 342 byte tableType = -1; 343 344 int attCount = infoset.getAttributeCount(); 345 PSVInfoset attInfoSet = null; 346 347 for (int i = 0; i < attCount; i++) 348 { 349 attInfoSet = infoset.getAttributePSVInfoset(i); 350 if (attInfoSet.getLocalName().equals(DBMS_TYPE_ATTR)) 351 dbmsType = attInfoSet.getNormalizedValue(); 352 else if (attInfoSet.getLocalName().equals(TYPE_ATTR)) 353 tableType = ((Number )attInfoSet.getActualValue()).byteValue(); 354 else if (attInfoSet.getLocalName().equals(CAT_ATTR)) 355 cat = ((Number )attInfoSet.getActualValue()).byteValue(); 356 else if (attInfoSet.getLocalName().equals(DBMS_ATTR)) 357 dbms = ((Number )attInfoSet.getActualValue()).byteValue(); 358 else if (attInfoSet.getLocalName().equals(SUFFIX_ATTR)) 359 suffix = attInfoSet.getNormalizedValue(); 360 else if (attInfoSet.getLocalName().equals(SEQ_ATTR)) 361 seq = ((Boolean )attInfoSet.getActualValue()).booleanValue(); 362 } 363 364 wTable.set(cat, tableType, seq, suffix, dbms, dbmsType); 365 wTable.setColumns((ColumnSpec[])columns.toArray(new ColumnSpec[columns.size()])); 366 wTable.setConstraints((ConstraintSpec[])constraints.toArray(new ConstraintSpec[constraints.size()])); 367 wTable.setIndexes((IndexSpec[])indexes.toArray(new IndexSpec[indexes.size()])); 368 369 370 ((List)tables[cat]).add(wTable); 371 372 373 columns.clear(); 374 indexes.clear(); 375 constraints.clear(); 376 } 377 378 void fillColumnType(ElementPSVInfoset infoset) 379 { 380 wColumn.setDataType(infoset.getAttributePSVInfoset( 381 null, JDBC_TYPE_ATTR).getNormalizedValue()); 382 } 383 384 void fillSize(ElementPSVInfoset infoset) 385 { 386 wColumn.setSize ( 387 ((Number )infoset.getActualValue()).longValue(), 388 ((Number )infoset.getAttributePSVInfoset(null, PARAM_ATTR).getActualValue()).shortValue() 389 ); 390 } 391 392 void fillPrecision(ElementPSVInfoset infoset) 393 { 394 wColumn.setPrecision ( 395 ((Number )infoset.getActualValue()).intValue(), 396 ((Number )infoset.getAttributePSVInfoset(null, PARAM_ATTR).getActualValue()).shortValue() 397 ); 398 } 399 400 void fillScale(ElementPSVInfoset infoset) 401 { 402 wColumn.setScale ( 403 ((Number )infoset.getActualValue()).intValue(), 404 ((Number )infoset.getAttributePSVInfoset(null, PARAM_ATTR).getActualValue()).shortValue() 405 ); 406 } 407 408 void completeColumn(ElementPSVInfoset infoset) 409 { 410 int attCount = infoset.getAttributeCount(); 411 PSVInfoset attInfoSet = null; 412 413 String name = null; 414 415 for (int i = 0; i < attCount; i++) 416 { 417 attInfoSet = infoset.getAttributePSVInfoset(i); 418 if (attInfoSet.getLocalName().equals(NAME_ATTR)) 419 { 420 name = attInfoSet.getNormalizedValue(); 421 wColumn.setName(name); 422 } 423 else if (attInfoSet.getLocalName().equals(KEY_ATTR)) 424 wColumn.setKeyRole(((Boolean )attInfoSet.getActualValue()).booleanValue()); 425 else if (attInfoSet.getLocalName().equals(NULLABLE_ATTR)) 426 wColumn.setNullable(((Boolean )attInfoSet.getActualValue()).booleanValue()); 427 } 428 429 if (name != null) 430 { 431 columnMap.put(name, wColumn); 432 columns.add(wColumn); 433 } 434 } 435 436 void createIndex(ElementPSVInfoset infoset) 437 { 438 String type = null; 439 String suffix = null; 440 List indexColumns = new ArrayList(); 441 442 int attCount = infoset.getAttributeCount(); 443 PSVInfoset attInfoSet = null; 444 445 for (int i = 0; i < attCount; i++) 446 { 447 attInfoSet = infoset.getAttributePSVInfoset(i); 448 if (attInfoSet.getLocalName().equals(TYPE_ATTR)) 449 type = attInfoSet.getNormalizedValue(); 450 else if (attInfoSet.getLocalName().equals(SUFFIX_ATTR)) 451 suffix = attInfoSet.getNormalizedValue(); 452 else if (attInfoSet.getLocalName().equals(COLUMNS_ATTR)) 453 { 454 List columnNames = (List)attInfoSet.getActualValue(); 455 for (Iterator it = columnNames.iterator();it.hasNext();) { 456 String columnName = (String )it.next(); 457 wColumn = (ColumnSpec)columnMap.get(columnName); 458 if (wColumn == null) 459 throw new RuntimeException ("The " + columnName 460 + " column used in an index defined in tableSpec.xml does not exist."); 461 else 462 indexColumns.add(wColumn); 463 } 464 479 } 480 } 481 IndexSpec wIndex = new IndexSpec(wTable, type, suffix); 482 wIndex.setColumns((ColumnSpec[])indexColumns.toArray(new ColumnSpec[indexColumns.size()])); 483 indexes.add(wIndex); 484 } 485 486 void createConstraint(ElementPSVInfoset infoset) 487 { 488 String type = null; 489 List constraintColumns = new ArrayList(); 490 491 int attCount = infoset.getAttributeCount(); 492 PSVInfoset attInfoSet = null; 493 494 for (int i = 0; i < attCount; i++) 495 { 496 attInfoSet = infoset.getAttributePSVInfoset(i); 497 if (attInfoSet.getLocalName().equals(TYPE_ATTR)) 498 type = attInfoSet.getNormalizedValue(); 499 else if (attInfoSet.getLocalName().equals(COLUMNS_ATTR)) 500 { 501 List columnNames = (List)attInfoSet.getActualValue(); 502 for (Iterator it = columnNames.iterator();it.hasNext();) { 503 String columnName = (String )it.next(); 504 wColumn = (ColumnSpec)columnMap.get(columnName); 505 if (wColumn == null) 506 throw new RuntimeException ("The " + columnName 507 + " column used in an index defined in tableSpec.xml does not exist."); 508 else 509 constraintColumns.add(wColumn); 510 } 511 526 } 527 } 528 ConstraintSpec wIndex = new ConstraintSpec(type); 529 wIndex.setColumns((ColumnSpec[])constraintColumns.toArray(new ColumnSpec[constraintColumns.size()])); 530 constraints.add(wIndex); 531 } 532 533 } 534 | Popular Tags |