/*
* Copyright 2008, Unitils.org
*
* Licensed 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.
*/
package org.unitils.dbmaintainer.structure.impl;
import org.unitils.core.UnitilsException;
import org.unitils.core.dbsupport.DbSupport;
import org.unitils.dbmaintainer.structure.DataSetStructureGenerator;
import org.unitils.dbmaintainer.util.BaseDatabaseAccessor;
import static org.unitils.thirdparty.org.apache.commons.io.IOUtils.closeQuietly;
import org.unitils.util.PropertyUtils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Properties;
import java.util.Set;
/**
* Implementation of {@link DataSetStructureGenerator} that generates xml schema files for data sets.
* <p/>
* This will generate an xsd for each configured database schema. Each database schema will be described in an xsd named
* 'schema_name'.xsd. A general dataset.xsd will also be generated. This xsd refers to the database schema specific xsds.
*
* @author Tim Ducheyne
* @author Filip Neven
*/
public class XsdDataSetStructureGenerator extends BaseDatabaseAccessor implements DataSetStructureGenerator {
/* Property key for the target directory for the generated xsd files */
public static final String PROPKEY_XSD_DIR_NAME = "dataSetStructureGenerator.xsd.dirName";
/* Property key for the suffix to use when defining complex types for the table definitions */
public static final String PROPKEY_XSD_COMPLEX_TYPE_SUFFIX = "dataSetStructureGenerator.xsd.complexTypeSuffix";
/* The target directory for the xsd files */
private String xsdDirectoryName;
/* The suffix to use when defining complex types for the table definitions */
private String complexTypeSuffix;
/**
* Initializes the generator.
*
* @param configuration The config, not null
*/
@Override
protected void doInit(Properties configuration) {
xsdDirectoryName = PropertyUtils.getString(PROPKEY_XSD_DIR_NAME, configuration);
complexTypeSuffix = PropertyUtils.getString(PROPKEY_XSD_COMPLEX_TYPE_SUFFIX, configuration);
}
/**
* Generates the XSDs, and writes them to the target directory specified by the property {@link #PROPKEY_XSD_DIR_NAME}.
*/
public void generateDataSetStructure() {
File xsdDirectory = new File(xsdDirectoryName);
xsdDirectory.mkdirs();
generateDataSetXsd(xsdDirectory);
for (DbSupport dbSupport : dbSupports) {
generateDatabaseSchemaXsd(dbSupport, xsdDirectory);
}
}
/**
* Generates a general dataset xsd that will refer to database schema specific dataset XSDs.
*
* @param xsdDirectory The target directory, not null
*/
protected void generateDataSetXsd(File xsdDirectory) {
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(new File(xsdDirectory, "dataset.xsd")));
String defaultSchemaName = defaultDbSupport.getSchemaName();
writer.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
writer.write("<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" xmlns:dflt=\"" + defaultSchemaName + "\">\n");
for (DbSupport dbSupport : dbSupports) {
String schemaName = dbSupport.getSchemaName();
writer.write("\t<xsd:import namespace=\"" + schemaName + "\" schemaLocation=\"" + schemaName + ".xsd\" />\n");
}
writer.write("\t<xsd:element name=\"dataset\">\n");
writer.write("\t\t<xsd:complexType>\n");
writer.write("\t\t\t<xsd:choice minOccurs=\"0\" maxOccurs=\"unbounded\">\n");
Set<String> defaultSchemaTableNames = defaultDbSupport.getTableNames();
for (String tableName : defaultSchemaTableNames) {
writer.write("\t\t\t\t<xsd:element name=\"" + tableName + "\" type=\"dflt:" + tableName + complexTypeSuffix + "\" />\n");
}
writer.write("\t\t\t\t<xsd:any namespace=\"" + defaultSchemaName + "\" />\n");
writer.write("\t\t\t</xsd:choice>\n");
writer.write("\t\t</xsd:complexType>\n");
writer.write("\t</xsd:element>\n");
writer.write("</xsd:schema>\n");
} catch (Exception e) {
throw new UnitilsException("Error generating xsd file: " + xsdDirectory, e);
} finally {
closeQuietly(writer);
}
}
/**
* Generates an XSD for the database schema of the given db support.
*
* @param dbSupport The db support, not null
* @param xsdDirectory The target directory, not null
*/
protected void generateDatabaseSchemaXsd(DbSupport dbSupport, File xsdDirectory) {
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(new File(xsdDirectory, dbSupport.getSchemaName() + ".xsd")));
writer.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
writer.write("<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" xmlns=\"" + dbSupport.getSchemaName() + "\" targetNamespace=\"" + dbSupport.getSchemaName() + "\">\n");
Set<String> tableNames = dbSupport.getTableNames();
for (String tableName : tableNames) {
writer.write("\t<xsd:element name=\"" + tableName + "\" type=\"" + tableName + complexTypeSuffix + "\" />\n");
}
for (String tableName : tableNames) {
writer.write("\t<xsd:complexType name=\"" + tableName + complexTypeSuffix + "\">\n");
Set<String> columnNames = dbSupport.getColumnNames(tableName);
for (String columnName : columnNames) {
writer.write("\t\t<xsd:attribute name=\"" + columnName + "\" use=\"optional\" />\n");
}
writer.write("\t</xsd:complexType>\n");
}
writer.write("</xsd:schema>\n");
} catch (Exception e) {
throw new UnitilsException("Error generating xsd file: " + xsdDirectory, e);
} finally {
closeQuietly(writer);
}
}
}