/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.cmp.jdbc.metadata.parser;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import static org.jboss.as.cmp.CmpMessages.MESSAGES;
import org.jboss.as.cmp.jdbc.SQLUtil;
import org.jboss.as.cmp.jdbc.metadata.JDBCApplicationMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCCMPFieldPropertyMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCEntityCommandMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCFunctionMappingMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCLeftJoinMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCMappingMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCOptimisticLockingMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCQueryMetaDataFactory;
import org.jboss.as.cmp.jdbc.metadata.JDBCRelationMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCTypeMappingMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCUserTypeMappingMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCValueClassMetaData;
import org.jboss.as.cmp.jdbc.metadata.JDBCValuePropertyMetaData;
import org.jboss.metadata.parser.util.MetaDataElementParser;
/**
* @author John Bailey
*/
public class JDBCMetaDataParser extends MetaDataElementParser {
public static JDBCApplicationMetaData parse(final XMLStreamReader reader, final JDBCApplicationMetaData defaults) throws XMLStreamException {
moveToStart(reader);
final ParsedApplication application = new ParsedApplication();
for (Element element : children(reader)) {
switch (element) {
case DEFAULTS: {
application.defaultEntity = parseEntity(reader, defaults.getClassLoader());
break;
}
case RELATIONSHIPS: {
application.relationships = parseRelationships(reader);
break;
}
case ENTERPRISE_BEANS: {
application.entities = parseEnterpriseBeans(reader, defaults.getClassLoader());
break;
}
case TYPE_MAPPINGS: {
application.typeMappings = parseTypeMappings(reader);
break;
}
case ENTITY_COMMANDS: {
application.entityCommands = parseEntityCommands(reader, defaults.getClassLoader());
break;
}
case DEPENDENT_VALUE_CLASSES: {
application.valueClasses = parseDependentValueClasses(reader, defaults.getClassLoader());
break;
}
case USER_TYPE_MAPPINGS: {
application.userTypeMappings = parseUserTypeMappings(reader);
break;
}
case RESERVED_WORDS: {
parseReservedWords(reader);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return new JDBCApplicationMetaData(application, defaults);
}
private static List<JDBCTypeMappingMetaData> parseTypeMappings(final XMLStreamReader reader) throws XMLStreamException {
final List<JDBCTypeMappingMetaData> typeMappings = new ArrayList<JDBCTypeMappingMetaData>();
for (Element element : children(reader)) {
switch (element) {
case TYPE_MAPPING: {
typeMappings.add(parseTypeMapping(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return typeMappings;
}
private static JDBCTypeMappingMetaData parseTypeMapping(final XMLStreamReader reader) throws XMLStreamException {
final JDBCTypeMappingMetaData metaData = new JDBCTypeMappingMetaData();
for (Element element : children(reader)) {
switch (element) {
case NAME: {
metaData.setName(getElementText(reader));
break;
}
case ADD_COLUMN_TEMPLATE: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setAddColumnTemplate(new JDBCFunctionMappingMetaData("add-column-template", value));
} else {
metaData.setAddColumnTemplate(new JDBCFunctionMappingMetaData("add-column-template", "ALTER TABLE ?1 ADD ?2 ?3"));
}
break;
}
case ALIAS_HEADER_PREFIX: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setAliasHeaderPrefix(value);
}
break;
}
case ALIAS_HEADER_SUFFIX: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setAliasHeaderSuffix(value);
}
break;
}
case ALIAS_MAX_LENGHT: {
final String value = getElementText(reader);
try {
final int aliasMaxLength = Integer.parseInt(value);
metaData.setAliasMaxLength(aliasMaxLength);
} catch (NumberFormatException e) {
throw MESSAGES.invalidNumberFormat("alias-max-length", value);
}
break;
}
case ALTER_COLUMN_TEMPLATE: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setAlterColumnTemplate(new JDBCFunctionMappingMetaData("add-column-template", value));
} else {
metaData.setAlterColumnTemplate(new JDBCFunctionMappingMetaData("add-column-template", "ALTER TABLE ?1 ADD ?2 ?3"));
}
break;
}
case AUTO_INCREMENT_TEMPLATE: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setAutoIncrementTemplate(new JDBCFunctionMappingMetaData("auto-increment", value));
}
break;
}
case DROP_COLUMN_TEMPLATE: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setDropColumnTemplate(new JDBCFunctionMappingMetaData("drop-column-template", value));
} else {
metaData.setDropColumnTemplate(new JDBCFunctionMappingMetaData("drop-column-template", "ALTER TABLE ?1 DROP ?2"));
}
break;
}
case FALSE_MAPPING: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setFalseMapping(value);
}
break;
}
case FK_CONSTRAINT_TEMPLATE: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setFKConstraintTemplate(new JDBCFunctionMappingMetaData("fk-constraint", value));
}
break;
}
case FUNCTION_MAPPING: {
metaData.addFunctionMapping(parseFunctionMapping(reader));
break;
}
case MAPPING: {
metaData.addMapping(parseMapping(reader));
break;
}
case MAX_KEYS_IN_DELETE: {
final String value = getElementText(reader);
try {
final int maxKeys = Integer.parseInt(value);
metaData.setMaxKeysInDelete(maxKeys);
} catch (NumberFormatException e) {
throw MESSAGES.invalidNumberFormat("max-keys-in-delete", value);
}
break;
}
case PK_CONSTRAINT_TEMPLATE: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setPKConstraintTemplate(new JDBCFunctionMappingMetaData("pk-constraint", value));
}
break;
}
case ROW_LOCKING_TEMPLATE: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setRowLockingTemplate(new JDBCFunctionMappingMetaData("row-locking", value));
}
break;
}
case SUBQUERY_SUPPORTED: {
metaData.setSubQuerySupported(Boolean.valueOf(getElementText(reader)));
break;
}
case TRUE_MAPPING: {
final String value = getElementText(reader);
if (!isEmpty(value)) {
metaData.setTrueMapping(value);
}
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static JDBCFunctionMappingMetaData parseFunctionMapping(final XMLStreamReader reader) throws XMLStreamException {
final JDBCFunctionMappingMetaData metaData = new JDBCFunctionMappingMetaData();
for (Element element : children(reader)) {
switch (element) {
case FUNCTION_NAME: {
metaData.setFunctionName(getElementText(reader));
break;
}
case FUNCTION_SQL: {
metaData.setFunctionSql(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static JDBCMappingMetaData parseMapping(final XMLStreamReader reader) throws XMLStreamException {
final JDBCMappingMetaData metaData = new JDBCMappingMetaData();
for (Element element : children(reader)) {
switch (element) {
case JAVA_TYPE: {
metaData.setJavaType(getElementText(reader));
break;
}
case JDBC_TYPE: {
metaData.setJdbcType(getJdbcTypeFromName(getElementText(reader)));
break;
}
case SQL_TYPE: {
metaData.setSqlType(getElementText(reader));
break;
}
case PARAM_SETTER: {
metaData.setParamSetter(getElementText(reader));
break;
}
case RESULT_READER: {
metaData.setResultReader(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static ParsedReadAhead parseReadAhead(final XMLStreamReader reader) throws XMLStreamException {
final ParsedReadAhead metaData = new ParsedReadAhead();
final List<JDBCLeftJoinMetaData> leftJoins = new ArrayList<JDBCLeftJoinMetaData>();
for (Element element : children(reader)) {
switch (element) {
case STRATEGY: {
metaData.strategy = getElementText(reader);
break;
}
case PAGE_SIZE: {
metaData.pageSize = Integer.parseInt(getElementText(reader));
break;
}
case EAGER_LOAD_GROUP: {
metaData.eagerLoadGroup = getElementText(reader);
break;
}
case LEFT_JOIN: {
leftJoins.add(parseLeftJoin(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
metaData.leftJoinList = leftJoins;
return metaData;
}
private static JDBCLeftJoinMetaData parseLeftJoin(XMLStreamReader reader) throws XMLStreamException {
final JDBCLeftJoinMetaData metaData = new JDBCLeftJoinMetaData();
final List<JDBCLeftJoinMetaData> leftJoins = new ArrayList<JDBCLeftJoinMetaData>();
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case CMR_FIELD: {
metaData.setCmrField(reader.getAttributeValue(i));
break;
}
case EAGER_LOAD_GROUP: {
metaData.setEagerLoadGroup(reader.getAttributeValue(i));
break;
}
default: {
throw unexpectedAttribute(reader, i);
}
}
}
for (Element element : children(reader)) {
switch (element) {
case LEFT_JOIN: {
leftJoins.add(parseLeftJoin(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
metaData.setLeftJoins(leftJoins);
return metaData;
}
private static ParsedCmpField parseUnknownPk(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final ParsedCmpField parsedCmpField = new ParsedCmpField();
for (Element element : children(reader)) {
switch (element) {
case UNKNOWN_KEY_CLASS: {
String type = getElementText(reader);
try {
parsedCmpField.unknownPk = classLoader.loadClass(type);
} catch (ClassNotFoundException e) {
throw MESSAGES.failedToLoadFieldType(type, e);
}
break;
}
case FIELD_NAME: {
parsedCmpField.fieldName = getElementText(reader);
break;
}
case READ_ONLY: {
parsedCmpField.readOnly = Boolean.parseBoolean(getElementText(reader));
break;
}
case READ_TIMEOUT: {
parsedCmpField.readTimeOut = Integer.parseInt(getElementText(reader));
break;
}
case COLUMN_NAME: {
parsedCmpField.columnName = getElementText(reader);
break;
}
case JDBC_TYPE: {
parsedCmpField.jdbcType = getJdbcTypeFromName(getElementText(reader));
break;
}
case SQL_TYPE: {
parsedCmpField.sqlType = getElementText(reader);
break;
}
case AUTO_INCREMENT: {
parsedCmpField.autoIncrement = Boolean.parseBoolean(getElementText(reader));
break;
}
case KEY_GENERATOR_FACTORY: {
getElementText(reader); // TODO: Is this used?
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return parsedCmpField;
}
private static JDBCEntityCommandMetaData parseEntityCommand(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final JDBCEntityCommandMetaData metaData = new JDBCEntityCommandMetaData();
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case NAME: {
metaData.setName(reader.getAttributeValue(i));
break;
}
case CLASS: {
final String command = reader.getAttributeValue(i);
try {
metaData.setClass(classLoader.loadClass(command));
} catch (ClassNotFoundException e) {
throw MESSAGES.failedToLoadEntityCommand(command, e);
}
break;
}
default: {
throw unexpectedAttribute(reader, i);
}
}
}
for (Element element : children(reader)) {
switch (element) {
case ATTRIBUTE: {
parseAttribute(reader, metaData);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static void parseAttribute(final XMLStreamReader reader, JDBCEntityCommandMetaData metaData) throws XMLStreamException {
String name = null;
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case NAME: {
name = reader.getAttributeValue(i);
break;
}
default: {
throw unexpectedAttribute(reader, i);
}
}
}
final String value = getElementText(reader);
if (name != null) {
metaData.addAttribute(name, value);
}
}
private static List<JDBCEntityCommandMetaData> parseEntityCommands(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final List<JDBCEntityCommandMetaData> commands = new ArrayList<JDBCEntityCommandMetaData>();
for (Element element : children(reader)) {
switch (element) {
case ENTITY_COMMAND: {
commands.add(parseEntityCommand(reader, classLoader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return commands;
}
private static List<ParsedRelationship> parseRelationships(final XMLStreamReader reader) throws XMLStreamException {
final List<ParsedRelationship> relationships = new ArrayList<ParsedRelationship>();
for (Element element : children(reader)) {
switch (element) {
case EJB_RELATION: {
relationships.add(parseRelationship(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return relationships;
}
private static ParsedRelationship parseRelationship(final XMLStreamReader reader) throws XMLStreamException {
final ParsedRelationship metaData = new ParsedRelationship();
for (Element element : children(reader)) {
switch (element) {
case EJB_RELATION_NAME: {
metaData.relationName = getElementText(reader);
break;
}
case READ_ONLY: {
metaData.readOnly = Boolean.parseBoolean(getElementText(reader));
break;
}
case READ_TIMEOUT: {
metaData.readTimeOut = Integer.parseInt(getElementText(reader));
break;
}
case FOREIGN_KEY_MAPPING: {
metaData.mappingStyle = JDBCRelationMetaData.MappingStyle.FOREIGN_KEY;
getElementText(reader);
break;
}
case RELATION_TABLE_MAPPING: {
metaData.mappingStyle = JDBCRelationMetaData.MappingStyle.TABLE;
for (Element tableElement : children(reader)) {
switch (tableElement) {
case TABLE_NAME: {
metaData.tableName = getElementText(reader);
break;
}
case DATASOURCE: {
metaData.dataSourceName = getElementText(reader);
break;
}
case DATASOURCE_MAPPING: {
metaData.datasourceMapping = getElementText(reader);
break;
}
case CREATE_TABLE: {
metaData.createTable = Boolean.parseBoolean(getElementText(reader));
break;
}
case REMOVE_TABLE: {
metaData.removeTable = Boolean.parseBoolean(getElementText(reader));
break;
}
case ALTER_TABLE: {
metaData.alterTable = Boolean.parseBoolean(getElementText(reader));
break;
}
case POST_TABLE_CREATE: {
for (String cmd : parsePostTableCreate(reader)) {
metaData.tablePostCreateCmd.add(cmd);
}
break;
}
case ROW_LOCKING: {
metaData.rowLocking = Boolean.parseBoolean(getElementText(reader));
break;
}
case PK_CONSTRAINT: {
metaData.primaryKeyConstraint = Boolean.parseBoolean(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
break;
}
case EJB_RELATIONSHIP_ROLE: {
metaData.roles.add(parseEjbRelationshipRole(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static ParsedRelationshipRole parseEjbRelationshipRole(final XMLStreamReader reader) throws XMLStreamException {
final ParsedRelationshipRole metaData = new ParsedRelationshipRole();
for (Element element : children(reader)) {
switch (element) {
case EJB_RELATIONSHIP_ROLE_NAME: {
metaData.relationshipRoleName = getElementText(reader);
break;
}
case FK_CONSTRAINT: {
metaData.foreignKeyConstraint = Boolean.parseBoolean(getElementText(reader));
break;
}
case READ_AHEAD: {
metaData.readAhead = parseReadAhead(reader);
break;
}
case KEY_FIELDS: {
metaData.keyFields = parseKeyFields(reader);
break;
}
case BATCH_CASCADE_DELETE: {
metaData.batchCascadeDelete = Boolean.parseBoolean(getElementText(reader));
break;
}
case CMR_FIELD: {
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static List<ParsedCmpField> parseKeyFields(final XMLStreamReader reader) throws XMLStreamException {
final List<ParsedCmpField> parsedCmpFields = new ArrayList<ParsedCmpField>();
for (Element element : children(reader)) {
switch (element) {
case KEY_FIELD: {
parsedCmpFields.add(parseCmpField(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return parsedCmpFields;
}
private static JDBCCMPFieldPropertyMetaData parseProperty(final XMLStreamReader reader) throws XMLStreamException {
final JDBCCMPFieldPropertyMetaData metaData = new JDBCCMPFieldPropertyMetaData();
for (Element element : children(reader)) {
switch (element) {
case PROPERTY_NAME: {
metaData.setPropertyName(getElementText(reader));
break;
}
case COLUMN_NAME: {
metaData.setColumnName(getElementText(reader));
break;
}
case NOT_NULL: {
metaData.setNotNul(Boolean.parseBoolean(getElementText(reader)));
break;
}
case JDBC_TYPE: {
metaData.setJdbcType(getJdbcTypeFromName(getElementText(reader)));
break;
}
case SQL_TYPE: {
metaData.setSqlType(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static List<String> parsePostTableCreate(XMLStreamReader reader) throws XMLStreamException {
final List<String> statements = new ArrayList<String>();
for (Element element : children(reader)) {
switch (element) {
case SQL_STATEMENT: {
statements.add(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return statements;
}
private static List<ParsedEntity> parseEnterpriseBeans(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final List<ParsedEntity> entities = new ArrayList<ParsedEntity>();
for (Element element : children(reader)) {
switch (element) {
case ENTITY: {
entities.add(parseEntity(reader, classLoader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return entities;
}
private static ParsedEntity parseEntity(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final ParsedEntity metaData = new ParsedEntity();
for (Element element : children(reader)) {
switch (element) {
case EJB_NAME: {
metaData.entityName = getElementText(reader);
break;
}
case DATASOURCE: {
metaData.dataSourceName = getElementText(reader);
break;
}
case DATASOURCE_MAPPING: {
metaData.dataSourceMappingName = getElementText(reader);
break;
}
case CREATE_TABLE: {
metaData.createTable = Boolean.parseBoolean(getElementText(reader));
break;
}
case REMOVE_TABLE: {
metaData.removeTable = Boolean.parseBoolean(getElementText(reader));
break;
}
case POST_TABLE_CREATE: {
for (String cmd : parsePostTableCreate(reader)) {
metaData.tablePostCreateCmd.add(cmd);
}
break;
}
case READ_ONLY: {
metaData.readOnly = Boolean.parseBoolean(getElementText(reader));
break;
}
case READ_TIMEOUT: {
metaData.readTimeOut = Integer.parseInt(getElementText(reader));
break;
}
case ROW_LOCKING: {
metaData.rowLocking = Boolean.parseBoolean(getElementText(reader));
break;
}
case PK_CONSTRAINT: {
metaData.primaryKeyConstraint = Boolean.parseBoolean(getElementText(reader));
break;
}
case FK_CONSTRAINT: {
metaData.preferredMappingStyle = getElementText(reader);
break;
}
case READ_AHEAD: {
metaData.readAhead = parseReadAhead(reader);
break;
}
case LIST_CACHE_MAX: {
metaData.listCacheMax = Integer.parseInt(getElementText(reader));
break;
}
case CLEAN_READ_AHEAD: {
metaData.cleanReadAheadOnLoad = Boolean.parseBoolean(getElementText(reader));
break;
}
case FETCH_SIZE: {
metaData.fetchSize = Integer.parseInt(getElementText(reader));
break;
}
case TABLE_NAME: {
metaData.tableName = getElementText(reader);
break;
}
case CMP_FIELD: {
metaData.cmpFields.add(parseCmpField(reader));
break;
}
case LOAD_GROUPS: {
metaData.loadGroups.putAll(parseLoadGroups(reader));
break;
}
case EAGER_LOAD_GROUP: {
metaData.eagerLoadGroup = getElementText(reader);
break;
}
case LAZY_LOAD_GROUPS: {
metaData.lazyLoadGroups.addAll(parseLazyLoadGroups(reader));
break;
}
case QUERY: {
metaData.queries.add(parseQuery(reader, classLoader));
break;
}
case UNKNOWN_PK: {
metaData.upkField = parseUnknownPk(reader, classLoader);
break;
}
case ENTITY_COMMAND: {
metaData.entityCommand = parseEntityCommand(reader, classLoader);
break;
}
case OPTIMISTIC_LOCKING: {
metaData.optimisticLocking = parseOptimisticLocking(reader, classLoader);
break;
}
case AUDIT: {
metaData.audit = parseAudit(reader);
break;
}
case PREFERRED_RELATION: {
getElementText(reader); // TODO: jeb How to handle this
break;
}
case QL_COMPILER: {
final String qlCompiler = getElementText(reader);
try {
metaData.qlCompiler = classLoader.loadClass(qlCompiler);
} catch (ClassNotFoundException e) {
throw MESSAGES.failedToLoadCompiler(qlCompiler, e);
}
break;
}
case THROW_RUNTIME_EX: {
metaData.throwRuntimeExceptions = Boolean.valueOf(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static List<String> parseLazyLoadGroups(XMLStreamReader reader) throws XMLStreamException {
final List<String> groups = new ArrayList<String>();
for (Element element : children(reader)) {
switch (element) {
case LOAD_GROUP_NAME: {
groups.add(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return groups;
}
private static ParsedQuery parseQuery(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final ParsedQuery metaData = new ParsedQuery();
for (Element element : children(reader)) {
switch (element) {
case QUERY_METHOD: {
for (Element queryMethodChild : children(reader)) {
switch (queryMethodChild) {
case METHOD_NAME: {
metaData.methodName = getElementText(reader);
break;
}
case METHOD_PARAMS: {
for (Element paramChild : children(reader)) {
switch (paramChild) {
case METHOD_PARAM: {
metaData.methodParams.add(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
break;
}
case JBOSS_QL: {
metaData.type = JDBCQueryMetaDataFactory.Type.JBOSS_QL;
metaData.query = getElementText(reader);
break;
}
case DYNAMIC_QL: {
metaData.type = JDBCQueryMetaDataFactory.Type.DYNAMIC_QL;
getElementText(reader);
break;
}
case DECLARED_QL: {
metaData.type = JDBCQueryMetaDataFactory.Type.DECLARED_QL;
for (Element declaredChild : children(reader)) {
switch (declaredChild) {
case FROM: {
metaData.declaredParts.put("from", getElementText(reader));
break;
}
case WHERE: {
metaData.declaredParts.put("where", getElementText(reader));
break;
}
case ORDER: {
metaData.declaredParts.put("order", getElementText(reader));
break;
}
case OTHER: {
metaData.declaredParts.put("other", getElementText(reader));
break;
}
case SELECT: {
for (Element selectChild : children(reader)) {
switch (selectChild) {
case DISTINCT: {
metaData.declaredParts.put("distinct", getElementText(reader));
break;
}
case EJB_NAME: {
metaData.declaredParts.put("ejb-name", getElementText(reader));
break;
}
case FIELD_NAME: {
metaData.declaredParts.put("field-name", getElementText(reader));
break;
}
case ALIAS: {
metaData.declaredParts.put("alias", getElementText(reader));
break;
}
case ADDITIONAL_COLUMNS: {
metaData.declaredParts.put("additional-columns", getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
break;
}
case RAW_SQL: {
metaData.type = JDBCQueryMetaDataFactory.Type.RAW_SQL;
metaData.query = getElementText(reader);
break;
}
case READ_AHEAD: {
metaData.readAheadMetaData = parseReadAhead(reader);
break;
}
case QL_COMPILER: {
final String qlCompiler = getElementText(reader);
try {
metaData.qlCompiler = classLoader.loadClass(qlCompiler);
} catch (ClassNotFoundException e) {
throw MESSAGES.failedToLoadCompiler(qlCompiler, e);
}
break;
}
case LAZY_RESULTSET_LOADING: {
metaData.lazyResultsetLoading = Boolean.parseBoolean(getElementText(reader));
break;
}
case DESCRIPTION: {
getElementText(reader);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static ParsedAudit parseAudit(final XMLStreamReader reader) throws XMLStreamException {
final ParsedAudit metaData = new ParsedAudit();
for (Element element : children(reader)) {
switch (element) {
case CREATED_BY: {
metaData.createdBy = parseAuditField(reader, "audit_created_by");
break;
}
case CREATED_TIME: {
metaData.createdTime = parseAuditField(reader, "audit_created_time");
break;
}
case UPDATED_BY: {
metaData.updatedBy = parseAuditField(reader, "audit_updated_by");
break;
}
case UPDATED_TIME: {
metaData.updatedTime = parseAuditField(reader, "audit_updated_time");
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static ParsedCmpField parseAuditField(XMLStreamReader reader, String fieldName) throws XMLStreamException {
final ParsedCmpField field = parseCmpField(reader);
if (field.fieldName == null) {
field.fieldName = fieldName;
}
if (field.columnName == null) {
field.columnName = fieldName;
}
return field;
}
private static ParsedOptimisticLocking parseOptimisticLocking(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final ParsedOptimisticLocking metaData = new ParsedOptimisticLocking();
ParsedCmpField lockingField = null;
for (Element element : children(reader)) {
switch (element) {
case GROUP_NAME: {
metaData.lockingStrategy = JDBCOptimisticLockingMetaData.LockingStrategy.FIELD_GROUP_STRATEGY;
metaData.groupName = getElementText(reader);
break;
}
case MODIFIED_STRATEGY: {
metaData.lockingStrategy = JDBCOptimisticLockingMetaData.LockingStrategy.MODIFIED_STRATEGY;
getElementText(reader);
break;
}
case READ_STRATEGY: {
metaData.lockingStrategy = JDBCOptimisticLockingMetaData.LockingStrategy.READ_STRATEGY;
getElementText(reader);
break;
}
case VERSION_COLUMN: {
metaData.lockingStrategy = JDBCOptimisticLockingMetaData.LockingStrategy.VERSION_COLUMN_STRATEGY;
getElementText(reader);
break;
}
case TIMESTAMP_COLUMN: {
metaData.lockingStrategy = JDBCOptimisticLockingMetaData.LockingStrategy.TIMESTAMP_COLUMN_STRATEGY;
getElementText(reader);
break;
}
case KEY_GENERATOR_FACTORY: {
metaData.lockingStrategy = JDBCOptimisticLockingMetaData.LockingStrategy.KEYGENERATOR_COLUMN_STRATEGY;
metaData.keyGeneratorFactory = getElementText(reader);
break;
}
case FIELD_TYPE: {
if (lockingField == null) lockingField = new ParsedCmpField();
final String type = getElementText(reader);
try {
lockingField.fieldType = classLoader.loadClass(type);
} catch (ClassNotFoundException e) {
throw MESSAGES.failedToLoadFieldType(type, e);
}
break;
}
case FIELD_NAME: {
if (lockingField == null) lockingField = new ParsedCmpField();
lockingField.fieldName = getElementText(reader);
break;
}
case COLUMN_NAME: {
if (lockingField == null) lockingField = new ParsedCmpField();
lockingField.columnName = getElementText(reader);
break;
}
case JDBC_TYPE: {
if (lockingField == null) lockingField = new ParsedCmpField();
lockingField.jdbcType = getJdbcTypeFromName(getElementText(reader));
break;
}
case SQL_TYPE: {
if (lockingField == null) lockingField = new ParsedCmpField();
lockingField.sqlType = getElementText(reader);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
metaData.lockingField = lockingField;
return metaData;
}
private static Map<String, List<String>> parseLoadGroups(final XMLStreamReader reader) throws XMLStreamException {
final Map<String, List<String>> groups = new HashMap<String, List<String>>();
for (Element element : children(reader)) {
switch (element) {
case LOAD_GROUP: {
parseLoadGroup(reader, groups);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return groups;
}
private static void parseLoadGroup(final XMLStreamReader reader, Map<String, List<String>> groups) throws XMLStreamException {
String groupName = null;
final List<String> fields = new ArrayList<String>();
for (Element element : children(reader)) {
switch (element) {
case LOAD_GROUP_NAME: {
groupName = getElementText(reader);
break;
}
case FIELD_NAME: {
fields.add(getElementText(reader));
break;
}
case DESCRIPTION: {
getElementText(reader);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
if (groupName != null) {
groups.put(groupName, fields);
}
}
private static ParsedCmpField parseCmpField(final XMLStreamReader reader) throws XMLStreamException {
final ParsedCmpField metaData = new ParsedCmpField();
for (Element element : children(reader)) {
switch (element) {
case COLUMN_NAME: {
metaData.columnName = getElementText(reader);
break;
}
case FIELD_NAME: {
metaData.fieldName = getElementText(reader);
break;
}
case READ_ONLY: {
metaData.readOnly = Boolean.parseBoolean(getElementText(reader));
break;
}
case READ_TIMEOUT: {
metaData.readTimeOut = Integer.parseInt(getElementText(reader));
break;
}
case NOT_NULL: {
metaData.notNull = Boolean.parseBoolean(getElementText(reader));
break;
}
case JDBC_TYPE: {
metaData.jdbcType = getJdbcTypeFromName(getElementText(reader));
break;
}
case SQL_TYPE: {
metaData.sqlType = getElementText(reader);
break;
}
case PROPERTY: {
metaData.propertyOverrides.add(parseProperty(reader));
break;
}
case AUTO_INCREMENT: {
getElementText(reader);
metaData.autoIncrement = true;
break;
}
case DB_INDEX: {
getElementText(reader);
metaData.genIndex = true;
break;
}
case CHECK_DIRTY_AFTER_GET: {
metaData.checkDirtyAfterGet = Boolean.parseBoolean(getElementText(reader));
break;
}
case STATE_FACTORY: {
metaData.stateFactory = getElementText(reader);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static List<JDBCValueClassMetaData> parseDependentValueClasses(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final List<JDBCValueClassMetaData> valueClasses = new ArrayList<JDBCValueClassMetaData>();
for (Element element : children(reader)) {
switch (element) {
case DEPENDENT_VALUE_CLASS: {
valueClasses.add(parseValueClass(reader, classLoader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return valueClasses;
}
private static JDBCValueClassMetaData parseValueClass(final XMLStreamReader reader, final ClassLoader classLoader) throws XMLStreamException {
final Map<String, JDBCValuePropertyMetaData> properties = new HashMap<String, JDBCValuePropertyMetaData>();
final JDBCValueClassMetaData valueClass = new JDBCValueClassMetaData();
for (Element element : children(reader)) {
switch (element) {
case CLASS: {
final String type = getElementText(reader);
try {
valueClass.setClass(classLoader.loadClass(type));
} catch (ClassNotFoundException e) {
throw MESSAGES.failedToLoadValueClass(type, e);
}
break;
}
case PROPERTY: {
parseValueProperty(reader, properties);
break;
}
case DESCRIPTION: {
getElementText(reader);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
for (String propertyName : properties.keySet()) {
final JDBCValuePropertyMetaData propertyMetaData = properties.get(propertyName);
propertyMetaData.setPropertyName(propertyName, valueClass.getJavaType());
valueClass.addProperty(propertyMetaData);
}
return valueClass;
}
private static void parseValueProperty(final XMLStreamReader reader, final Map<String, JDBCValuePropertyMetaData> properties) throws XMLStreamException {
String propertyName = null;
final JDBCValuePropertyMetaData metaData = new JDBCValuePropertyMetaData();
for (Element element : children(reader)) {
switch (element) {
case PROPERTY_NAME: {
propertyName = getElementText(reader);
break;
}
case COLUMN_NAME: {
metaData.setColumnName(getElementText(reader));
break;
}
case NOT_NULL: {
metaData.setNotNul(Boolean.parseBoolean(getElementText(reader)));
break;
}
case JDBC_TYPE: {
metaData.setJdbcType(getJdbcTypeFromName(getElementText(reader)));
break;
}
case SQL_TYPE: {
metaData.setSqlType(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
properties.put(propertyName, metaData);
}
private static List<JDBCUserTypeMappingMetaData> parseUserTypeMappings(final XMLStreamReader reader) throws XMLStreamException {
final List<JDBCUserTypeMappingMetaData> userTypeMappings = new ArrayList<JDBCUserTypeMappingMetaData>();
for (Element element : children(reader)) {
switch (element) {
case USER_TYPE_MAPPING: {
userTypeMappings.add(parseUserTypeMapping(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return userTypeMappings;
}
private static JDBCUserTypeMappingMetaData parseUserTypeMapping(final XMLStreamReader reader) throws XMLStreamException {
final JDBCUserTypeMappingMetaData metaData = new JDBCUserTypeMappingMetaData();
for (Element element : children(reader)) {
switch (element) {
case JAVA_TYPE: {
metaData.setJavaType(getElementText(reader));
break;
}
case MAPPED_TYPE: {
metaData.setMappedType(getElementText(reader));
break;
}
case MAPPER: {
metaData.setMapper(getElementText(reader));
break;
}
case CHECK_DIRTY_AFTER_GET: {
metaData.setCheckDirtyAfterGet(Boolean.parseBoolean(getElementText(reader)));
break;
}
case STATE_FACTORY: {
metaData.setStateFactory(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return metaData;
}
private static void parseReservedWords(final XMLStreamReader reader) throws XMLStreamException {
for (Element element : children(reader)) {
switch (element) {
case WORD: {
SQLUtil.addToRwords(getElementText(reader));
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private static void moveToStart(final XMLStreamReader reader) throws XMLStreamException {
reader.require(START_DOCUMENT, null, null);
while (reader.hasNext() && reader.next() != START_ELEMENT) {
}
}
private static boolean isEmpty(final String value) {
return value == null || value.trim().equals("");
}
/**
* Gets the JDBC type constant int for the name. The mapping from name to jdbc
* type is contained in java.sql.Types.
*
* @param name the name for the jdbc type
* @return the int type constant from java.sql.Types
* @see java.sql.Types
*/
public static int getJdbcTypeFromName(String name) {
if (name == null) {
throw MESSAGES.jdbcTypeCanNotBeNull();
}
try {
return (Integer) Types.class.getField(name).get(null);
} catch (Exception e) {
return Types.OTHER;
}
}
private static Iterable<Element> children(final XMLStreamReader reader) throws XMLStreamException {
return new Iterable<Element>() {
public Iterator<Element> iterator() {
return new Iterator<Element>() {
public boolean hasNext() {
try {
return reader.hasNext() && reader.nextTag() != END_ELEMENT;
} catch (XMLStreamException e) {
throw MESSAGES.unableToGetNextElement(e);
}
}
public Element next() {
return Element.forName(reader.getLocalName());
}
public void remove() {
throw MESSAGES.removeNotSupported();
}
};
}
};
}
}