Java tutorial
package org.apache.torque.templates.transformer.sql; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.apache.torque.generator.control.ControllerState; import org.apache.torque.generator.source.SourceElement; import org.apache.torque.generator.source.SourcePath; import org.apache.torque.generator.source.transform.SourceTransformer; import org.apache.torque.generator.source.transform.SourceTransformerException; import org.apache.torque.templates.TemplateOptionName; import org.apache.torque.templates.TorqueSchemaAttributeName; import org.apache.torque.templates.TorqueSchemaElementName; import org.apache.torque.templates.TorqueSchemaIdMethod; import org.apache.torque.templates.platform.Platform; import org.apache.torque.templates.platform.PlatformFactory; import org.apache.torque.templates.transformer.CollectAttributeSetTrueTransformer; import org.apache.torque.templates.transformer.IncludeSchemaTransformer; import org.apache.torque.templates.transformer.LoadExternalSchemaTransformer; import org.apache.torque.templates.transformer.SchemaTypeHelper; import org.apache.torque.templates.transformer.om.DatabaseChildElementName; import org.apache.torque.templates.transformer.om.OMColumnTransformer; import org.apache.torque.templates.transformer.om.OMTransformer; import org.apache.torque.templates.transformer.om.TableChildElementName; import org.apache.torque.templates.typemapping.SchemaType; import org.apache.torque.templates.typemapping.SqlType; import org.apache.torque.templates.typemapping.TypeMap; /** * Transforms the tables in the OM model for sql generation. */ public class SQLTransformer implements SourceTransformer { /** A CollectAttributeSetTrueTransformer instance. */ private static final CollectAttributeSetTrueTransformer collectAttributeSetTrueTransformer = new CollectAttributeSetTrueTransformer(); /** * The transformer which loads the external schemata. * * @see LoadExternalSchemaTransformer */ private static final SourceTransformer loadExternalSchemaTransformer = new LoadExternalSchemaTransformer(); /** * The transformer which includes the included schemata. * * @see LoadExternalSchemaTransformer */ private static final SourceTransformer includeSchemaTransformer = new IncludeSchemaTransformer(); public SourceElement transform(SourceElement databaseElement, ControllerState controllerState) throws SourceTransformerException { OMTransformer.setRootDatabaseNameAttribute(databaseElement); // include included schemata includeSchemaTransformer.transform(databaseElement, controllerState); // load referenced external schemata loadExternalSchemaTransformer.transform(databaseElement, controllerState); TemplateOptionName.checkRequiredOptions(controllerState, TemplateOptionName.DATABASE); List<SourceElement> allTables = databaseElement.getChild(DatabaseChildElementName.ALL_TABLES) .getChildren(TorqueSchemaElementName.TABLE); for (SourceElement tableElement : allTables) { transformTable(tableElement, controllerState); } addDatabaseSchemaElements(databaseElement, controllerState); return databaseElement; } public void transformTable(SourceElement tableElement, ControllerState controllerState) throws SourceTransformerException { String tableName = (String) tableElement.getAttribute(TorqueSchemaAttributeName.NAME); String unqualifiedTableName = tableName; if (StringUtils.contains(tableName, ".")) { unqualifiedTableName = tableName.substring(tableName.indexOf(".") + 1); } tableElement.setAttribute(SqlAttributeName.UNQUALIFIED_NAME, unqualifiedTableName); Object idMethod = tableElement.getAttribute(TorqueSchemaAttributeName.ID_METHOD.getName()); if (idMethod == null) { Object defaultIdMethod = tableElement.getParent() .getAttribute(TorqueSchemaAttributeName.DEFAULT_ID_METHOD.getName()); if (defaultIdMethod == null) { throw new SourceTransformerException("id Method is not set" + " on table " + tableElement.getAttribute(TorqueSchemaAttributeName.NAME.getName()) + " and defaultIdMethod is not set on database"); } tableElement.setAttribute(TorqueSchemaAttributeName.ID_METHOD.getName(), defaultIdMethod); } if (tableElement.getAttribute(SqlAttributeName.PRIMARY_KEY_CONSTRAINT_NAME) == null) { String primaryKeyConstraintName = unqualifiedTableName + "_PK"; tableElement.setAttribute(SqlAttributeName.PRIMARY_KEY_CONSTRAINT_NAME, primaryKeyConstraintName); } if (tableElement.getAttribute(SqlAttributeName.SEQUENCE_NAME) == null) { String sequenceName = null; SourceElement idMethodParameterElement = tableElement .getChild(TorqueSchemaElementName.ID_METHOD_PARAMETER); if (idMethodParameterElement != null) { sequenceName = (String) idMethodParameterElement.getAttribute(TorqueSchemaAttributeName.VALUE); } if (StringUtils.isBlank(sequenceName)) { sequenceName = tableName + "_SEQ"; } tableElement.setAttribute(SqlAttributeName.SEQUENCE_NAME, sequenceName); } // primary keys collectAttributeSetTrueTransformer.transform(tableElement, controllerState, TorqueSchemaElementName.COLUMN, TorqueSchemaAttributeName.PRIMARY_KEY, TableChildElementName.PRIMARY_KEYS); StringBuilder primaryKeyColumnNames = new StringBuilder(); SourceElement primaryKeysElement = tableElement.getChild(TableChildElementName.PRIMARY_KEYS); boolean firstPk = true; for (SourceElement primaryKeyColumn : primaryKeysElement.getChildren()) { if (!firstPk) { primaryKeyColumnNames.append(", "); } primaryKeyColumnNames.append(primaryKeyColumn.getAttribute(TorqueSchemaAttributeName.NAME.getName())); firstPk = false; } tableElement.setAttribute(SqlAttributeName.PRIMARY_KEY_COLUMN_NAMES, primaryKeyColumnNames.toString()); // unique int uniqueIndex = 1; for (SourceElement uniqueElement : tableElement.getChildren(TorqueSchemaElementName.UNIQUE.getName())) { if (uniqueElement.getAttribute(TorqueSchemaAttributeName.NAME.getName()) == null) { uniqueElement.setAttribute(TorqueSchemaAttributeName.NAME.getName(), uniqueElement.getParent().getAttribute(TorqueSchemaAttributeName.NAME.getName()) + "_UQ_" + uniqueIndex); } String uniqueColumnNames = collectAttributes(uniqueElement, TorqueSchemaElementName.UNIQUE_COLUMN.getName(), TorqueSchemaAttributeName.NAME.getName()); uniqueElement.setAttribute(SqlAttributeName.UNIQUE_COLUMN_NAMES, uniqueColumnNames); ++uniqueIndex; } // index int indexIndex = 1; for (SourceElement indexElement : tableElement.getChildren(TorqueSchemaElementName.INDEX.getName())) { if (indexElement.getAttribute(TorqueSchemaAttributeName.NAME.getName()) == null) { indexElement.setAttribute(TorqueSchemaAttributeName.NAME.getName(), indexElement.getParent().getAttribute(TorqueSchemaAttributeName.NAME.getName()) + "_IDX_" + indexIndex); } String indexColumnNames = collectAttributes(indexElement, TorqueSchemaElementName.INDEX_COLUMN.getName(), TorqueSchemaAttributeName.NAME.getName()); indexElement.setAttribute(SqlAttributeName.INDEX_COLUMN_NAMES, indexColumnNames); indexIndex++; } List<SourceElement> columnElements = tableElement.getChildren(TorqueSchemaElementName.COLUMN.getName()); for (SourceElement columnElement : columnElements) { transformColumn(columnElement, controllerState); } List<SourceElement> foreignKeyElements = tableElement .getChildren(TorqueSchemaElementName.FOREIGN_KEY.getName()); int fkIndex = 1; for (SourceElement foreignKeyElemenElement : foreignKeyElements) { transformForeignKey(foreignKeyElemenElement, controllerState, fkIndex); ++fkIndex; } } /** * Enriches the column elements with additional attributes * needed for SQL generation. * * @param columnElement the element to enrich, not null. * @param controllerState the current controller state, not null. * * @throws SourceTransformerException if the name or type attributes * are not set or if the type is unknown. */ private void transformColumn(SourceElement columnElement, ControllerState controllerState) throws SourceTransformerException { String sql = (String) columnElement.getAttribute(SqlAttributeName.DDL_SQL); if (sql == null) { sql = getDdlSql(columnElement, controllerState); columnElement.setAttribute(SqlAttributeName.DDL_SQL, sql); } } /** * Creates the SQL for defining a column. * * @param columnElement the column element for which the SQL * should be created, not null. * @param controllerState the current controller state, not null. * * @return the SQL for defining the column, not null. * * @throws SourceTransformerException */ private String getDdlSql(SourceElement columnElement, ControllerState controllerState) throws SourceTransformerException { SchemaType schemaType = SchemaTypeHelper.getSchemaType(columnElement, controllerState); SqlType domainType = SchemaTypeHelper.getDomain(columnElement, controllerState); Object size = columnElement.getAttribute(TorqueSchemaAttributeName.SIZE); Object scale = columnElement.getAttribute(TorqueSchemaAttributeName.SCALE); Object defaultValue = columnElement.getAttribute(TorqueSchemaAttributeName.DEFAULT); SqlType sqlType = SchemaTypeHelper.getSqlType(schemaType, domainType, controllerState, ObjectUtils.toString(size, null), ObjectUtils.toString(scale, null), ObjectUtils.toString(defaultValue, null)); Platform platform = getPlatform(controllerState); List<String> resultList = new ArrayList<String>(); String sqlTypeName = sqlType.getSqlTypeName(); if (platform.hasSize(sqlTypeName)) { sqlTypeName += sqlType.printSize(platform.getSizeSuffix(sqlTypeName)); } resultList.add(sqlTypeName); if (StringUtils.isNotEmpty(sqlType.getDefaultValue())) { resultList.add("default"); if ((SchemaType.DATE == schemaType || SchemaType.TIME == schemaType || SchemaType.TIMESTAMP == schemaType)) { if (sqlType.getDefaultValue().startsWith("CURRENT_")) { resultList.add(sqlType.getDefaultValue()); } else { Date defaultDate = OMColumnTransformer.getDefaultValueAsDate(sqlType.getDefaultValue()); if (SchemaType.DATE == schemaType) { resultList.add(platform.getDateString(defaultDate)); } else if (SchemaType.TIME == schemaType) { resultList.add(platform.getTimeString(defaultDate)); } else { resultList.add(platform.getTimestampString(defaultDate)); } } } else if (TypeMap.isTextType(schemaType)) { resultList.add(platform.quoteAndEscape(sqlType.getDefaultValue())); } else { resultList.add(sqlType.getDefaultValue()); } } boolean primaryKey; { String primaryKeyString = (String) columnElement.getAttribute(TorqueSchemaAttributeName.PRIMARY_KEY); primaryKey = Boolean.parseBoolean(primaryKeyString); } boolean required; { String requiredString = (String) columnElement.getAttribute(TorqueSchemaAttributeName.REQUIRED); required = Boolean.parseBoolean(requiredString); } boolean isNotNull = primaryKey || required; String isNotNullString = platform.getNullString(isNotNull); if (platform.createNotNullBeforeAutoincrement() && StringUtils.isNotEmpty(isNotNullString)) { resultList.add(isNotNullString); } // if idMethod was not set explicitly by the user, // the transformTable() method sets the attribute from the // defaultIdMethod of the database, so this always returns // the id method Object idMethod = columnElement.getParent().getAttribute(TorqueSchemaAttributeName.ID_METHOD); if (primaryKey && TorqueSchemaIdMethod.NATIVE.getName().equals(idMethod)) { String autoIncrement = platform.getAutoIncrement(); if (StringUtils.isNotEmpty(autoIncrement)) { resultList.add(autoIncrement); } } if (!platform.createNotNullBeforeAutoincrement() && StringUtils.isNotEmpty(isNotNullString)) { resultList.add(isNotNullString); } return StringUtils.join(resultList.iterator(), ' '); } private Platform getPlatform(ControllerState controllerState) { Platform platform = PlatformFactory .getPlatformFor(controllerState.getStringOption(TemplateOptionName.DATABASE)); return platform; } /** * Sets additional attributes on foreign key elements. * * @param foreignKeyElement the foreign key element to enrich, not null. * @param controllerState the current controller state, not null. * @param fkIndex the number of the foreign-key element in the table. */ private void transformForeignKey(SourceElement foreignKeyElement, ControllerState controllerState, int fkIndex) { if (foreignKeyElement.getAttribute(TorqueSchemaAttributeName.NAME.getName()) == null) { foreignKeyElement.setAttribute(TorqueSchemaAttributeName.NAME.getName(), foreignKeyElement.getParent().getAttribute(TorqueSchemaAttributeName.NAME.getName()) + "_FK_" + fkIndex); } String localColumnsNames = collectAttributes(foreignKeyElement, TorqueSchemaElementName.REFERENCE.getName(), TorqueSchemaAttributeName.LOCAL.getName()); foreignKeyElement.setAttribute(SqlAttributeName.LOCAL_COLUMN_NAMES, localColumnsNames); String foreignColumnsNames = collectAttributes(foreignKeyElement, TorqueSchemaElementName.REFERENCE.getName(), TorqueSchemaAttributeName.FOREIGN.getName()); foreignKeyElement.setAttribute(SqlAttributeName.FOREIGN_COLUMN_NAMES, foreignColumnsNames); } private void addDatabaseSchemaElements(SourceElement databaseElement, ControllerState controllerState) { Platform platform = getPlatform(controllerState); if (!platform.usesStandaloneSchema()) { return; } List<String> databaseSchemaNames = new ArrayList<String>(); List<SourceElement> allTables = databaseElement.getChild(DatabaseChildElementName.ALL_TABLES) .getChildren(TorqueSchemaElementName.TABLE); for (SourceElement tableElement : allTables) { String name = (String) tableElement.getAttribute(TorqueSchemaAttributeName.NAME); if (StringUtils.contains(name, '.')) { String databaseSchema = name.substring(0, name.indexOf('.')); if (!databaseSchemaNames.contains(databaseSchema)) { databaseSchemaNames.add(databaseSchema); } } } for (String databaseSchemaName : databaseSchemaNames) { SourceElement databaseSchemaElement = new SourceElement("databaseSchema"); databaseSchemaElement.setAttribute("name", databaseSchemaName); databaseElement.getChildren().add(databaseSchemaElement); } } /** * Collects attribute values in a comma-separated string. * The elements on which the attribute values are read can be reached * from <code>rootElement</code> via the path <code>sourcePath</code>; * and on these elements, the attributes with name * <code>attributeName</code> are collected. * * @param rootElement the base element from where to start, not null. * @param sourcePath the path from <code>rootElement</code> to the elements * on which to collect the attributes. * @param attributeName the name of the attributes to collect. * * @return a comma-separated (", ") String containing all the matching * attribute values. */ private String collectAttributes(SourceElement rootElement, String sourcePath, String attributeName) { StringBuilder result = new StringBuilder(); List<SourceElement> toCollectFrom = SourcePath.getElements(rootElement, sourcePath); for (SourceElement sourceElement : toCollectFrom) { Object attributeValue = sourceElement.getAttribute(attributeName); if (attributeValue != null) { if (result.length() > 0) { result.append(", "); } result.append(sourceElement.getAttribute(attributeName)); } } return result.toString(); } }