mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
ALF-11256: SchemaBootstrap must compare running schema against reference dump
Reference schemas (e.g. classpath:org/alfresco/util/schemacomp/reference/PostgreSQLDialect-Reference.xml) are loaded (if present) and the database is compared to that reference schema. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@31991 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
parent
8bb6a9a372
commit
f5b08ab073
@ -18,13 +18,17 @@
|
||||
*/
|
||||
package org.alfresco.repo.domain.schema;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
@ -45,6 +49,7 @@ import java.sql.Statement;
|
||||
import java.sql.Struct;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -66,6 +71,13 @@ import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.util.LogUtil;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.alfresco.util.schemacomp.Difference;
|
||||
import org.alfresco.util.schemacomp.ExportDb;
|
||||
import org.alfresco.util.schemacomp.Results;
|
||||
import org.alfresco.util.schemacomp.SchemaComparator;
|
||||
import org.alfresco.util.schemacomp.ValidationResult;
|
||||
import org.alfresco.util.schemacomp.XMLToSchema;
|
||||
import org.alfresco.util.schemacomp.model.Schema;
|
||||
import org.alfresco.util.schemadump.Main;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@ -91,6 +103,8 @@ import org.hibernate.engine.ActionQueue;
|
||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
@ -1480,6 +1494,8 @@ public class SchemaBootstrap extends AbstractLifecycleBean
|
||||
setBootstrapCompleted(connection);
|
||||
}
|
||||
|
||||
validateSchema();
|
||||
|
||||
// Report normalized dumps
|
||||
if (executedStatements != null)
|
||||
{
|
||||
@ -1578,6 +1594,115 @@ public class SchemaBootstrap extends AbstractLifecycleBean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collate differences and validation problems with the schema with respect to an appropriate
|
||||
* reference schema.
|
||||
*/
|
||||
private void validateSchema()
|
||||
{
|
||||
Date startTime = new Date();
|
||||
String referenceFileName = dialect.getClass().getSimpleName() + "-Reference.xml";
|
||||
|
||||
Resource referenceResource = rpr.getResource("classpath:org/alfresco/util/schemacomp/reference/"
|
||||
+ referenceFileName);
|
||||
|
||||
if (!referenceResource.exists())
|
||||
{
|
||||
logger.info("No reference schema file, expected: " + referenceResource);
|
||||
return;
|
||||
}
|
||||
logger.info("Comparing database schema with reference schema: " + referenceResource);
|
||||
|
||||
InputStream is = null;
|
||||
try
|
||||
{
|
||||
is = new BufferedInputStream(referenceResource.getInputStream());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to open schema reference file: " + referenceResource);
|
||||
}
|
||||
|
||||
XMLToSchema xmlToSchema = new XMLToSchema(is);
|
||||
xmlToSchema.parse();
|
||||
Schema reference = xmlToSchema.getSchema();
|
||||
|
||||
ExportDb exporter = new ExportDb(dataSource, dialect);
|
||||
exporter.execute();
|
||||
Schema target = exporter.getSchema();
|
||||
|
||||
SchemaComparator schemaComparator = new SchemaComparator(reference, target, dialect);
|
||||
|
||||
schemaComparator.validateAndCompare();
|
||||
|
||||
Results differences = schemaComparator.getDifferences();
|
||||
List<ValidationResult> validationResults = schemaComparator.getValidationResults();
|
||||
|
||||
File outputFile = TempFileProvider.createTempFile(
|
||||
"Alfresco-" + dialect.getClass().getSimpleName() + "-Validation", ".txt");
|
||||
|
||||
logger.info("Writing schema validation results to: " + outputFile);
|
||||
|
||||
PrintWriter pw = null;
|
||||
try
|
||||
{
|
||||
pw = new PrintWriter(outputFile);
|
||||
}
|
||||
catch (FileNotFoundException error)
|
||||
{
|
||||
throw new RuntimeException("Unable to open file for writing: " + outputFile);
|
||||
}
|
||||
|
||||
for (Difference difference : differences)
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(difference.getStrength())
|
||||
.append(" (diff): ")
|
||||
.append(difference.getWhere());
|
||||
|
||||
sb.append(" reference: ");
|
||||
if (difference.getLeft() != null)
|
||||
{
|
||||
sb.append(difference.getLeft().getPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("null");
|
||||
}
|
||||
|
||||
sb.append(" target: ");
|
||||
if (difference.getRight() != null)
|
||||
{
|
||||
sb.append(difference.getRight().getPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("null");
|
||||
}
|
||||
|
||||
pw.println(sb);
|
||||
}
|
||||
|
||||
for (ValidationResult validationResult : validationResults)
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(validationResult.getStrength())
|
||||
.append(" (validation): ")
|
||||
.append("target: ")
|
||||
.append(validationResult.getDbProperty().getPath())
|
||||
.append(" value: ")
|
||||
.append(validationResult.getValue());
|
||||
|
||||
pw.println(sb);
|
||||
}
|
||||
|
||||
pw.close();
|
||||
|
||||
Date endTime = new Date();
|
||||
long durationMillis = endTime.getTime() - startTime.getTime();
|
||||
logger.info("Schema validation took " + durationMillis + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the file that was written to or <tt>null</tt> if it failed
|
||||
*/
|
||||
|
@ -29,7 +29,6 @@ import org.alfresco.util.schemacomp.model.PrimaryKey;
|
||||
import org.alfresco.util.schemacomp.model.Schema;
|
||||
import org.alfresco.util.schemacomp.model.Table;
|
||||
import org.alfresco.util.schemacomp.validator.DbValidator;
|
||||
import org.apache.poi.hssf.record.DVALRecord;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
@ -91,12 +90,12 @@ public class DbObjectXMLTransformer
|
||||
* @param validators
|
||||
* @throws SAXException
|
||||
*/
|
||||
private void transformValidators(List<DbValidator<? extends DbObject>> validators) throws SAXException
|
||||
private void transformValidators(List<DbValidator> validators) throws SAXException
|
||||
{
|
||||
if (validators.size() > 0)
|
||||
{
|
||||
simpleStartTag(XML.EL_VALIDATORS);
|
||||
for (DbValidator<? extends DbObject> dbv : validators)
|
||||
for (DbValidator dbv : validators)
|
||||
{
|
||||
final AttributesImpl attribs = new AttributesImpl();
|
||||
attribs.addAttribute("", "", XML.ATTR_CLASS, "CDATA", dbv.getClass().getName());
|
||||
|
@ -34,7 +34,6 @@ import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -47,7 +46,6 @@ import javax.xml.transform.sax.TransformerHandler;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.alfresco.util.schemacomp.model.Column;
|
||||
import org.alfresco.util.schemacomp.model.DbObject;
|
||||
import org.alfresco.util.schemacomp.model.ForeignKey;
|
||||
import org.alfresco.util.schemacomp.model.Index;
|
||||
import org.alfresco.util.schemacomp.model.PrimaryKey;
|
||||
@ -268,7 +266,7 @@ public class DbObjectXMLTransformerTest
|
||||
|
||||
NameValidator nameValidator = new NameValidator();
|
||||
nameValidator.setPattern(Pattern.compile("match_me_if_you_can"));
|
||||
List<DbValidator<? extends DbObject>> validators = new ArrayList<DbValidator<? extends DbObject>>();
|
||||
List<DbValidator> validators = new ArrayList<DbValidator>();
|
||||
validators.add(nameValidator);
|
||||
table.setValidators(validators);
|
||||
|
||||
|
@ -58,11 +58,12 @@ public class ExportDb
|
||||
|
||||
private Dialect dialect;
|
||||
|
||||
private String namePrefix = "%";
|
||||
/** Only top-level tables starting with namePrefix will be exported, set to empty string for all objects */
|
||||
private String namePrefix = "alf_";
|
||||
|
||||
|
||||
|
||||
public ExportDb(ApplicationContext context) throws Exception
|
||||
public ExportDb(ApplicationContext context)
|
||||
{
|
||||
this((DataSource) context.getBean("dataSource"),
|
||||
(Dialect) context.getBean("dialect"));
|
||||
@ -75,7 +76,7 @@ public class ExportDb
|
||||
* @param connection the database connection to use for metadata queries
|
||||
* @param dialect the Hibernate dialect
|
||||
*/
|
||||
public ExportDb(final DataSource dataSource, final Dialect dialect) throws Exception
|
||||
public ExportDb(final DataSource dataSource, final Dialect dialect)
|
||||
{
|
||||
this.dataSource = dataSource;
|
||||
this.dialect = dialect;
|
||||
@ -83,12 +84,41 @@ public class ExportDb
|
||||
}
|
||||
|
||||
|
||||
private void init()
|
||||
{
|
||||
try
|
||||
{
|
||||
attemptInit();
|
||||
}
|
||||
catch (SecurityException error)
|
||||
{
|
||||
throw new RuntimeException("Unable to generate type map using hibernate.", error);
|
||||
}
|
||||
catch (IllegalArgumentException error)
|
||||
{
|
||||
throw new RuntimeException("Unable to generate type map using hibernate.", error);
|
||||
}
|
||||
catch (NoSuchFieldException error)
|
||||
{
|
||||
throw new RuntimeException("Unable to generate type map using hibernate.", error);
|
||||
}
|
||||
catch (IllegalAccessException error)
|
||||
{
|
||||
throw new RuntimeException("Unable to generate type map using hibernate.", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the fields ready to perform the database metadata reading
|
||||
* @param dialect the Hibernate dialect
|
||||
* @throws NoSuchFieldException
|
||||
* @throws SecurityException
|
||||
* @throws IllegalAccessException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void init() throws Exception
|
||||
private void attemptInit() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
final Field typeNamesField = Dialect.class.getDeclaredField("typeNames");
|
||||
typeNamesField.setAccessible(true);
|
||||
@ -205,7 +235,7 @@ public class ExportDb
|
||||
|
||||
String nullableString = columns.getString("IS_NULLABLE");
|
||||
column.setNullable(parseBoolean(nullableString));
|
||||
|
||||
column.setParent(table);
|
||||
table.getColumns().add(column);
|
||||
}
|
||||
columns.close();
|
||||
@ -231,6 +261,7 @@ public class ExportDb
|
||||
// If this table has a primary key, add it.
|
||||
if (pk != null)
|
||||
{
|
||||
pk.setParent(table);
|
||||
table.setPrimaryKey(pk);
|
||||
}
|
||||
|
||||
@ -259,6 +290,7 @@ public class ExportDb
|
||||
{
|
||||
index = new Index(indexName);
|
||||
index.setUnique(!indexes.getBoolean("NON_UNIQUE"));
|
||||
index.setParent(table);
|
||||
table.getIndexes().add(index);
|
||||
lastIndexName = indexName;
|
||||
}
|
||||
@ -283,6 +315,7 @@ public class ExportDb
|
||||
if (!keyName.equals(lastKeyName))
|
||||
{
|
||||
fk = new ForeignKey(keyName);
|
||||
fk.setParent(table);
|
||||
table.getForeignKeys().add(fk);
|
||||
lastKeyName = keyName;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ package org.alfresco.util.schemacomp;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Iterator;
|
||||
@ -30,6 +32,7 @@ import org.alfresco.util.schemacomp.model.Column;
|
||||
import org.alfresco.util.schemacomp.model.DbObject;
|
||||
import org.alfresco.util.schemacomp.model.ForeignKey;
|
||||
import org.alfresco.util.schemacomp.model.Index;
|
||||
import org.alfresco.util.schemacomp.model.PrimaryKey;
|
||||
import org.alfresco.util.schemacomp.model.Schema;
|
||||
import org.alfresco.util.schemacomp.model.Sequence;
|
||||
import org.alfresco.util.schemacomp.model.Table;
|
||||
@ -55,7 +58,6 @@ public class ExportDbTest
|
||||
exporter = new ExportDb(ctx);
|
||||
}
|
||||
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void exportDb() throws Exception
|
||||
@ -64,6 +66,8 @@ public class ExportDbTest
|
||||
exporter.execute();
|
||||
|
||||
Schema schema = exporter.getSchema();
|
||||
|
||||
assertNull("Schema shouldn't have a parent", schema.getParent());
|
||||
System.out.println(schema);
|
||||
|
||||
Table appliedPatchTable = null;
|
||||
@ -87,10 +91,10 @@ public class ExportDbTest
|
||||
}
|
||||
|
||||
checkResultsFiltered(schema, "alf_");
|
||||
checkAppliedPatchTable(appliedPatchTable);
|
||||
checkQNameTable(qNameTable);
|
||||
checkAppliedPatchTable(schema, appliedPatchTable);
|
||||
checkQNameTable(schema, qNameTable);
|
||||
// TODO: what to do about sequences? They can't easily be retrieved with JDBC's DatabaseMetaData
|
||||
//checkAuthoritySequence(authoritySeq);
|
||||
//checkAuthoritySequence(schema, authoritySeq);
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +120,7 @@ public class ExportDbTest
|
||||
/**
|
||||
* @param qNameTable
|
||||
*/
|
||||
private void checkQNameTable(Table qNameTable)
|
||||
private void checkQNameTable(Schema schema, Table qNameTable)
|
||||
{
|
||||
/*
|
||||
CREATE TABLE alf_qname
|
||||
@ -133,24 +137,30 @@ public class ExportDbTest
|
||||
*/
|
||||
|
||||
assertNotNull("Couldn't find table alf_qname", qNameTable);
|
||||
assertSame("Incorrect parent or no parent set", schema, qNameTable.getParent());
|
||||
|
||||
Iterator<Column> colIt = qNameTable.getColumns().iterator();
|
||||
Column col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, col.getParent());
|
||||
assertEquals("id", col.getName());
|
||||
assertEquals("int8", col.getType());
|
||||
assertEquals(false, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, col.getParent());
|
||||
assertEquals("version", col.getName());
|
||||
assertEquals("int8", col.getType());
|
||||
assertEquals(false, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, col.getParent());
|
||||
assertEquals("ns_id", col.getName());
|
||||
assertEquals("int8", col.getType());
|
||||
assertEquals(false, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, col.getParent());
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, col.getParent());
|
||||
assertEquals("local_name", col.getName());
|
||||
assertEquals("varchar(200)", col.getType());
|
||||
assertEquals(false, col.isNullable());
|
||||
@ -159,6 +169,7 @@ public class ExportDbTest
|
||||
Iterator<Index> indexIt = qNameTable.getIndexes().iterator();
|
||||
|
||||
Index index = indexIt.next();
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, index.getParent());
|
||||
assertEquals("ns_id", index.getName());
|
||||
assertEquals(true, index.isUnique());
|
||||
assertEquals(2, index.getColumnNames().size());
|
||||
@ -166,14 +177,18 @@ public class ExportDbTest
|
||||
assertEquals("local_name", index.getColumnNames().get(1));
|
||||
|
||||
index = indexIt.next();
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, index.getParent());
|
||||
assertEquals("fk_alf_qname_ns", index.getName());
|
||||
assertEquals(1, index.getColumnNames().size());
|
||||
assertEquals("ns_id", index.getColumnNames().get(0));
|
||||
|
||||
assertEquals("id", qNameTable.getPrimaryKey().getColumnNames().get(0));
|
||||
PrimaryKey pk = qNameTable.getPrimaryKey();
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, pk.getParent());
|
||||
assertEquals("id", pk.getColumnNames().get(0));
|
||||
|
||||
assertEquals(1, qNameTable.getForeignKeys().size());
|
||||
ForeignKey fk = qNameTable.getForeignKeys().get(0);
|
||||
assertSame("Incorrect parent or no parent set", qNameTable, fk.getParent());
|
||||
assertEquals("fk_alf_qname_ns", fk.getName());
|
||||
assertEquals("ns_id", fk.getLocalColumn());
|
||||
assertEquals("alf_namespace", fk.getTargetTable());
|
||||
@ -184,7 +199,7 @@ public class ExportDbTest
|
||||
/**
|
||||
* @param appliedPatch
|
||||
*/
|
||||
private void checkAppliedPatchTable(Table appliedPatch)
|
||||
private void checkAppliedPatchTable(Schema schema, Table appliedPatch)
|
||||
{
|
||||
/*
|
||||
CREATE TABLE alf_applied_patch
|
||||
@ -205,73 +220,88 @@ public class ExportDbTest
|
||||
*/
|
||||
assertNotNull("Couldn't find alf_applied_patch", appliedPatch);
|
||||
|
||||
assertSame("Incorrect parent or no parent set", schema, appliedPatch.getParent());
|
||||
assertEquals("alf_applied_patch", appliedPatch.getName());
|
||||
Iterator<Column> colIt = appliedPatch.getColumns().iterator();
|
||||
Column col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("id", col.getName());
|
||||
assertEquals("varchar(64)", col.getType());
|
||||
assertEquals(false, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("description", col.getName());
|
||||
assertEquals("varchar(1024)", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("fixes_from_schema", col.getName());
|
||||
assertEquals("int4", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("fixes_to_schema", col.getName());
|
||||
assertEquals("int4", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("applied_to_schema", col.getName());
|
||||
assertEquals("int4", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("target_schema", col.getName());
|
||||
assertEquals("int4", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("applied_on_date", col.getName());
|
||||
assertEquals("timestamp", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("applied_to_server", col.getName());
|
||||
assertEquals("varchar(64)", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("was_executed", col.getName());
|
||||
assertEquals("bool", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("succeeded", col.getName());
|
||||
assertEquals("bool", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
col = colIt.next();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, col.getParent());
|
||||
assertEquals("report", col.getName());
|
||||
assertEquals("varchar(1024)", col.getType());
|
||||
assertEquals(true, col.isNullable());
|
||||
|
||||
assertEquals("id", appliedPatch.getPrimaryKey().getColumnNames().get(0));
|
||||
PrimaryKey pk = appliedPatch.getPrimaryKey();
|
||||
assertSame("Incorrect parent or no parent set", appliedPatch, pk.getParent());
|
||||
assertEquals("id", pk.getColumnNames().get(0));
|
||||
}
|
||||
|
||||
|
||||
public void checkAuthoritySequence(Sequence seq)
|
||||
public void checkAuthoritySequence(Schema schema, Sequence seq)
|
||||
{
|
||||
/*
|
||||
CREATE SEQUENCE alf_authority_seq START WITH 1 INCREMENT BY 1;
|
||||
*/
|
||||
assertNotNull("Couldn't find sequence alf_authority_seq", seq);
|
||||
assertSame("Incorrect parent or no parent set", schema, seq.getParent());
|
||||
assertEquals("alf_authority_seq", seq.getName());
|
||||
}
|
||||
}
|
||||
|
@ -26,34 +26,35 @@ import org.alfresco.util.schemacomp.model.Schema;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
||||
/**
|
||||
* Compares two abstract database schemas, a 'left' schema and a 'right' schema. The left schema is the primary
|
||||
* schema and all objects in the right schema are judged relative to it.
|
||||
* Compares two abstract database schemas, a reference schema and a target schema (the schema to check for validity).
|
||||
* The reference schema is the primary schema and all objects in the right schema are judged relative to it.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class SchemaComparator
|
||||
{
|
||||
private final Schema leftSchema;
|
||||
private final Schema rightSchema;
|
||||
private final Schema referenceSchema;
|
||||
private final Schema targetSchema;
|
||||
private final DiffContext ctx;
|
||||
|
||||
/**
|
||||
* Construct a comparator to compare schemas left and right.
|
||||
* Construct a comparator to compare a target schema against a reference schema. Validators supplied
|
||||
* by the reference schema will be used to validate the target schema.
|
||||
*
|
||||
* @param left
|
||||
* @param right
|
||||
* @param referenceSchema
|
||||
* @param targetSchema
|
||||
*/
|
||||
public SchemaComparator(Schema left, Schema right, Dialect dialect)
|
||||
public SchemaComparator(Schema referenceSchema, Schema targetSchema, Dialect dialect)
|
||||
{
|
||||
this.leftSchema = left;
|
||||
this.rightSchema = right;
|
||||
this.ctx = new DiffContext(dialect, new Results(), new ArrayList<ValidationResult>(), leftSchema, rightSchema);
|
||||
this.referenceSchema = referenceSchema;
|
||||
this.targetSchema = targetSchema;
|
||||
this.ctx = new DiffContext(dialect, new Results(), new ArrayList<ValidationResult>(), referenceSchema, targetSchema);
|
||||
}
|
||||
|
||||
|
||||
public void validateAndCompare()
|
||||
{
|
||||
validate();
|
||||
validateTargetSchema();
|
||||
compare();
|
||||
}
|
||||
|
||||
@ -63,18 +64,17 @@ public class SchemaComparator
|
||||
*/
|
||||
private void compare()
|
||||
{
|
||||
leftSchema.diff(rightSchema, ctx, Strength.ERROR);
|
||||
referenceSchema.diff(targetSchema, ctx, Strength.ERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate both schemas.
|
||||
* Validate the target schema against the reference schema using the reference schema's validators.
|
||||
*/
|
||||
private void validate()
|
||||
private void validateTargetSchema()
|
||||
{
|
||||
ValidatingVisitor validatingVisitor = new ValidatingVisitor(ctx);
|
||||
leftSchema.accept(validatingVisitor);
|
||||
rightSchema.accept(validatingVisitor);
|
||||
referenceSchema.accept(validatingVisitor);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
* Copytarget (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -50,15 +50,15 @@ import org.junit.Test;
|
||||
public class SchemaComparatorTest
|
||||
{
|
||||
private SchemaComparator comparator;
|
||||
private Schema left;
|
||||
private Schema right;
|
||||
private Schema reference;
|
||||
private Schema target;
|
||||
private Dialect dialect;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
left = new Schema("left_schema");
|
||||
right = new Schema("right_schema");
|
||||
reference = new Schema("reference_schema");
|
||||
target = new Schema("target_schema");
|
||||
dialect = new MySQL5InnoDBDialect();
|
||||
}
|
||||
|
||||
@ -66,24 +66,24 @@ public class SchemaComparatorTest
|
||||
@Test
|
||||
public void canPerformDiff()
|
||||
{
|
||||
// Left hand side's database objects.
|
||||
left.add(new Table(left, "tbl_no_diff", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)", "name VARCHAR2(150)"),
|
||||
// Reference schema's database objects.
|
||||
reference.add(new Table(reference, "tbl_no_diff", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)", "name VARCHAR2(150)"),
|
||||
pk("pk_tbl_no_diff", "id"), fkeys(fk("fk_tbl_no_diff", "nodeRef", "node", "nodeRef")),
|
||||
indexes("idx_node id nodeRef")));
|
||||
left.add(table("table_in_left"));
|
||||
left.add(new Table(left, "tbl_has_diff_pk", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)"),
|
||||
reference.add(table("table_in_reference"));
|
||||
reference.add(new Table(reference, "tbl_has_diff_pk", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)"),
|
||||
pk("pk_is_diff", "id"), fkeys(), indexes("idx_one id nodeRef", "idx_two id")));
|
||||
|
||||
// Right hand side's database objects.
|
||||
right.add(new Table(right, "tbl_no_diff", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)", "name VARCHAR2(150)"),
|
||||
// Target schema's database objects.
|
||||
target.add(new Table(target, "tbl_no_diff", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)", "name VARCHAR2(150)"),
|
||||
pk("pk_tbl_no_diff", "id"), fkeys(fk("fk_tbl_no_diff", "nodeRef", "node", "nodeRef")),
|
||||
indexes("idx_node id nodeRef")));
|
||||
right.add(new Table(right, "tbl_has_diff_pk", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)"),
|
||||
target.add(new Table(target, "tbl_has_diff_pk", columns("id NUMBER(10)", "nodeRef VARCHAR2(200)"),
|
||||
pk("pk_is_diff", "nodeRef"), fkeys(), indexes("idx_one id nodeRef", "idx_two [unique] id")));
|
||||
right.add(table("table_in_right"));
|
||||
target.add(table("table_in_target"));
|
||||
|
||||
|
||||
comparator = new SchemaComparator(left, right, dialect);
|
||||
comparator = new SchemaComparator(reference, target, dialect);
|
||||
comparator.validateAndCompare();
|
||||
|
||||
// See stdout for diagnostics dump...
|
||||
@ -95,59 +95,59 @@ public class SchemaComparatorTest
|
||||
|
||||
Iterator<Difference> it = differences.iterator();
|
||||
|
||||
// Schema names are different ("left_schema" vs "right_schema")
|
||||
// Schema names are different ("reference_schema" vs "target_schema")
|
||||
Difference diff = it.next();
|
||||
assertEquals(Where.IN_BOTH_BUT_DIFFERENCE, diff.getWhere());
|
||||
assertEquals("left_schema.name", diff.getLeft().getPath());
|
||||
assertEquals("right_schema.name", diff.getRight().getPath());
|
||||
assertSame(left, diff.getLeft().getDbObject());
|
||||
assertSame(right, diff.getRight().getDbObject());
|
||||
assertEquals("reference_schema.name", diff.getLeft().getPath());
|
||||
assertEquals("target_schema.name", diff.getRight().getPath());
|
||||
assertSame(reference, diff.getLeft().getDbObject());
|
||||
assertSame(target, diff.getRight().getDbObject());
|
||||
assertEquals("name", diff.getLeft().getPropertyName());
|
||||
assertEquals("left_schema", diff.getLeft().getPropertyValue());
|
||||
assertEquals("reference_schema", diff.getLeft().getPropertyValue());
|
||||
assertEquals("name", diff.getRight().getPropertyName());
|
||||
assertEquals("right_schema", diff.getRight().getPropertyValue());
|
||||
assertEquals("target_schema", diff.getRight().getPropertyValue());
|
||||
|
||||
// Table table_in_left only appears in the left schema
|
||||
// Table table_in_reference only appears in the reference schema
|
||||
diff = it.next();
|
||||
assertEquals(Where.ONLY_IN_LEFT, diff.getWhere());
|
||||
assertEquals("left_schema.table_in_left", diff.getLeft().getPath());
|
||||
assertEquals("reference_schema.table_in_reference", diff.getLeft().getPath());
|
||||
assertEquals(null, diff.getRight());
|
||||
assertEquals(null, diff.getLeft().getPropertyName());
|
||||
assertEquals(null, diff.getLeft().getPropertyValue());
|
||||
|
||||
// Table tbl_has_diff_pk has PK of "id" in left and "nodeRef" in right
|
||||
// Table tbl_has_diff_pk has PK of "id" in reference and "nodeRef" in target
|
||||
diff = it.next();
|
||||
assertEquals(Where.ONLY_IN_LEFT, diff.getWhere());
|
||||
assertEquals("left_schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getLeft().getPath());
|
||||
assertEquals("right_schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getRight().getPath());
|
||||
assertEquals("reference_schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getLeft().getPath());
|
||||
assertEquals("target_schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getRight().getPath());
|
||||
assertEquals("columnNames[0]", diff.getLeft().getPropertyName());
|
||||
assertEquals("id", diff.getLeft().getPropertyValue());
|
||||
assertEquals("columnNames", diff.getRight().getPropertyName());
|
||||
assertEquals(Arrays.asList("nodeRef"), diff.getRight().getPropertyValue());
|
||||
|
||||
// Table tbl_has_diff_pk has PK of "id" in left and "nodeRef" in right
|
||||
// Table tbl_has_diff_pk has PK of "id" in reference and "nodeRef" in target
|
||||
diff = it.next();
|
||||
assertEquals(Where.ONLY_IN_RIGHT, diff.getWhere());
|
||||
assertEquals("left_schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getLeft().getPath());
|
||||
assertEquals("right_schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getRight().getPath());
|
||||
assertEquals("reference_schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getLeft().getPath());
|
||||
assertEquals("target_schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getRight().getPath());
|
||||
assertEquals("columnNames", diff.getLeft().getPropertyName());
|
||||
assertEquals(Arrays.asList("id"), diff.getLeft().getPropertyValue());
|
||||
assertEquals("columnNames[0]", diff.getRight().getPropertyName());
|
||||
assertEquals("nodeRef", diff.getRight().getPropertyValue());
|
||||
|
||||
// idx_two is unique in the righ_schema but not in the left
|
||||
// idx_two is unique in the righ_schema but not in the reference
|
||||
diff = it.next();
|
||||
assertEquals("left_schema.tbl_has_diff_pk.idx_two.unique", diff.getLeft().getPath());
|
||||
assertEquals("right_schema.tbl_has_diff_pk.idx_two.unique", diff.getRight().getPath());
|
||||
assertEquals("reference_schema.tbl_has_diff_pk.idx_two.unique", diff.getLeft().getPath());
|
||||
assertEquals("target_schema.tbl_has_diff_pk.idx_two.unique", diff.getRight().getPath());
|
||||
assertEquals("unique", diff.getLeft().getPropertyName());
|
||||
assertEquals(false, diff.getLeft().getPropertyValue());
|
||||
assertEquals("unique", diff.getRight().getPropertyName());
|
||||
assertEquals(true, diff.getRight().getPropertyValue());
|
||||
|
||||
// Table table_in_right does not exist in the left schema
|
||||
// Table table_in_target does not exist in the reference schema
|
||||
diff = it.next();
|
||||
assertEquals(Where.ONLY_IN_RIGHT, diff.getWhere());
|
||||
assertEquals("right_schema.table_in_right", diff.getRight().getPath());
|
||||
assertEquals("target_schema.table_in_target", diff.getRight().getPath());
|
||||
assertEquals(null, diff.getLeft());
|
||||
assertEquals(null, diff.getRight().getPropertyName());
|
||||
assertEquals(null, diff.getRight().getPropertyValue());
|
||||
|
@ -18,14 +18,10 @@
|
||||
*/
|
||||
package org.alfresco.util.schemacomp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.util.schemacomp.model.DbObject;
|
||||
import org.alfresco.util.schemacomp.model.Index;
|
||||
import org.alfresco.util.schemacomp.validator.DbValidator;
|
||||
import org.alfresco.util.schemacomp.validator.NameValidator;
|
||||
import org.alfresco.util.schemacomp.validator.NullValidator;
|
||||
|
||||
/**
|
||||
* Invokes the correct validator for a given DbObject.
|
||||
@ -35,39 +31,38 @@ import org.alfresco.util.schemacomp.validator.NullValidator;
|
||||
public class ValidatingVisitor implements DbObjectVisitor
|
||||
{
|
||||
private DiffContext ctx;
|
||||
protected NameValidator indexNameValidator = new NameValidator();
|
||||
protected NullValidator defaultValidator = new NullValidator();
|
||||
protected ComparisonUtils comparisonUtils = new DefaultComparisonUtils();
|
||||
private ComparisonUtils comparisonUtils = new DefaultComparisonUtils();
|
||||
|
||||
public ValidatingVisitor(DiffContext ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
|
||||
protected DbValidator getValidatorFor(Class<? extends DbObject> c)
|
||||
{
|
||||
if (c.equals(Index.class))
|
||||
{
|
||||
return indexNameValidator;
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValidator;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DbObject referenceObj)
|
||||
{
|
||||
DbValidator validator = getValidatorFor(referenceObj.getClass());
|
||||
List<DbObject> matches = comparisonUtils.findEquivalentObjects(ctx.getTargetSchema(), referenceObj);
|
||||
|
||||
// TODO: if matches.size() > 1 then warn of possible redundant database objects
|
||||
|
||||
for (DbObject target : matches)
|
||||
// Validate each matching target object against the reference object
|
||||
// using each of the available validators for that reference object.
|
||||
for (DbValidator validator : referenceObj.getValidators())
|
||||
{
|
||||
validator.validate(referenceObj, target, ctx);
|
||||
for (DbObject target : matches)
|
||||
{
|
||||
validator.validate(referenceObj, target, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param comparisonUtils the comparisonUtils to set
|
||||
*/
|
||||
public void setComparisonUtils(ComparisonUtils comparisonUtils)
|
||||
{
|
||||
this.comparisonUtils = comparisonUtils;
|
||||
}
|
||||
}
|
||||
|
@ -19,21 +19,15 @@
|
||||
package org.alfresco.util.schemacomp;
|
||||
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.util.schemacomp.model.Column;
|
||||
import org.alfresco.util.schemacomp.model.DbObject;
|
||||
import org.alfresco.util.schemacomp.model.ForeignKey;
|
||||
import org.alfresco.util.schemacomp.model.Index;
|
||||
import org.alfresco.util.schemacomp.model.PrimaryKey;
|
||||
import org.alfresco.util.schemacomp.model.Schema;
|
||||
import org.alfresco.util.schemacomp.model.Sequence;
|
||||
import org.alfresco.util.schemacomp.model.Table;
|
||||
import org.alfresco.util.schemacomp.validator.DbValidator;
|
||||
import org.alfresco.util.schemacomp.validator.NameValidator;
|
||||
import org.hibernate.dialect.MySQL5InnoDBDialect;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -48,47 +42,59 @@ public class ValidatingVisitorTest
|
||||
{
|
||||
private DiffContext ctx;
|
||||
private ValidatingVisitor visitor;
|
||||
private Table table;
|
||||
private Table refTable;
|
||||
private Table targetTable;
|
||||
private Schema refSchema;
|
||||
private Schema targetSchema;
|
||||
private Index index;
|
||||
private Index refIndex;
|
||||
private Index targetIndex1;
|
||||
private Index targetIndex2;
|
||||
private Index targetIndex3;
|
||||
private List<DbValidator> validators;
|
||||
private ComparisonUtils comparisonUtils;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
index = new Index(table, "index_name", new ArrayList<String>());
|
||||
refTable = new Table("reference_table");
|
||||
refIndex = new Index(refTable, "index_name", Arrays.asList("a", "b", "c"));
|
||||
ctx = new DiffContext(new MySQL5InnoDBDialect(), new Results(),
|
||||
new ArrayList<ValidationResult>(), refSchema, targetSchema);
|
||||
visitor = new ValidatingVisitor(ctx);
|
||||
}
|
||||
|
||||
validators = new ArrayList<DbValidator>();
|
||||
validators.add(Mockito.mock(DbValidator.class));
|
||||
validators.add(Mockito.mock(DbValidator.class));
|
||||
refIndex.setValidators(validators);
|
||||
|
||||
@Test
|
||||
public void canGetCorrectValidator()
|
||||
{
|
||||
// Get references to the validator instances to test for
|
||||
DbValidator nullValidator = visitor.defaultValidator;
|
||||
DbValidator nameValidator = visitor.indexNameValidator;
|
||||
|
||||
assertSame(nullValidator, visitor.getValidatorFor(Column.class));
|
||||
assertSame(nullValidator, visitor.getValidatorFor(ForeignKey.class));
|
||||
assertSame(nameValidator, visitor.getValidatorFor(Index.class));
|
||||
assertSame(nullValidator, visitor.getValidatorFor(PrimaryKey.class));
|
||||
assertSame(nullValidator, visitor.getValidatorFor(Schema.class));
|
||||
assertSame(nullValidator, visitor.getValidatorFor(Sequence.class));
|
||||
assertSame(nullValidator, visitor.getValidatorFor(Table.class));
|
||||
targetTable = new Table("target_table");
|
||||
targetIndex1 = new Index(targetTable, "index_name", Arrays.asList("a", "b", "c"));
|
||||
targetIndex2 = new Index(targetTable, "another_index", Arrays.asList("a", "b", "c"));
|
||||
targetIndex3 = new Index(targetTable, "index_name", Arrays.asList("e", "f"));
|
||||
|
||||
comparisonUtils = Mockito.mock(ComparisonUtils.class);
|
||||
visitor.setComparisonUtils(comparisonUtils);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void canValidate()
|
||||
{
|
||||
visitor.indexNameValidator = Mockito.mock(NameValidator.class);
|
||||
visitor.comparisonUtils = Mockito.mock(ComparisonUtils.class);
|
||||
Mockito.when(visitor.comparisonUtils.findEquivalentObjects(refSchema, index)).
|
||||
thenReturn(Arrays.asList((DbObject)index));
|
||||
Mockito.when(comparisonUtils.findEquivalentObjects(refSchema, refIndex)).
|
||||
thenReturn(Arrays.asList((DbObject) targetIndex1, targetIndex2, targetIndex3));
|
||||
|
||||
// Validate all instances of the target schema's indexes that are equivalent to this index
|
||||
visitor.visit(index);
|
||||
visitor.visit(refIndex);
|
||||
|
||||
Mockito.verify(visitor.indexNameValidator).validate(index, index, ctx);
|
||||
Mockito.verify(validators.get(0)).validate(refIndex, targetIndex1, ctx);
|
||||
Mockito.verify(validators.get(0)).validate(refIndex, targetIndex2, ctx);
|
||||
Mockito.verify(validators.get(0)).validate(refIndex, targetIndex3, ctx);
|
||||
|
||||
Mockito.verify(validators.get(1)).validate(refIndex, targetIndex1, ctx);
|
||||
Mockito.verify(validators.get(1)).validate(refIndex, targetIndex2, ctx);
|
||||
Mockito.verify(validators.get(1)).validate(refIndex, targetIndex3, ctx);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ package org.alfresco.util.schemacomp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.xml.parsers.SAXParser;
|
||||
@ -107,6 +105,7 @@ public class XMLToSchema extends DefaultHandler
|
||||
{
|
||||
Column column = (Column) stack.pop();
|
||||
Table table = (Table) stack.peek();
|
||||
column.setParent(table);
|
||||
table.getColumns().add(column);
|
||||
}
|
||||
else if (qName.equals(XML.EL_PRIMARY_KEY))
|
||||
@ -119,34 +118,31 @@ public class XMLToSchema extends DefaultHandler
|
||||
{
|
||||
ForeignKey fk = (ForeignKey) stack.pop();
|
||||
Table table = (Table) stack.peek();
|
||||
fk.setParent(table);
|
||||
table.getForeignKeys().add(fk);
|
||||
}
|
||||
else if (qName.equals(XML.EL_INDEX))
|
||||
{
|
||||
Index index = (Index) stack.pop();
|
||||
Table table = (Table) stack.peek();
|
||||
index.setParent(table);
|
||||
table.getIndexes().add(index);
|
||||
}
|
||||
else if (qName.equals(XML.EL_SEQUENCE))
|
||||
{
|
||||
Sequence seq = (Sequence) stack.pop();
|
||||
seq.setParent(schema);
|
||||
schema.add(seq);
|
||||
}
|
||||
else if (qName.equals(XML.EL_VALIDATOR))
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
DbValidator<? extends DbObject> validator = (DbValidator<? extends DbObject>) stack.pop();
|
||||
DbValidator validator = (DbValidator) stack.pop();
|
||||
DbObject dbo = (DbObject) stack.peek();
|
||||
dbo.getValidators().add(validator);
|
||||
}
|
||||
else if (qName.equals(XML.EL_PROPERTY))
|
||||
{
|
||||
//stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts)
|
||||
throws SAXException
|
||||
@ -187,10 +183,10 @@ public class XMLToSchema extends DefaultHandler
|
||||
else if (qName.equals(XML.EL_VALIDATOR))
|
||||
{
|
||||
String className = atts.getValue(XML.ATTR_CLASS);
|
||||
DbValidator<? extends DbObject> validator = null;
|
||||
DbValidator validator = null;
|
||||
try
|
||||
{
|
||||
validator = (DbValidator<? extends DbObject>) Class.forName(className).newInstance();
|
||||
validator = (DbValidator) Class.forName(className).newInstance();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
@ -258,7 +254,7 @@ public class XMLToSchema extends DefaultHandler
|
||||
if (stack.peek() instanceof DbValidator)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
DbValidator<? extends DbObject> validator = (DbValidator<? extends DbObject>) stack.peek();
|
||||
DbValidator validator = (DbValidator) stack.peek();
|
||||
validator.setProperty(propName, propValue);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ package org.alfresco.util.schemacomp;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
@ -61,31 +63,38 @@ public class XMLToSchemaTest
|
||||
Schema schema = xmlToSchema.getSchema();
|
||||
|
||||
assertNotNull("A null Schema object was returned", schema);
|
||||
assertNull("Schema isn't meant to have a parent", schema.getParent());
|
||||
assertEquals("alfresco", schema.getName());
|
||||
|
||||
Iterator<DbObject> objects = schema.iterator();
|
||||
|
||||
Table table = (Table) objects.next();
|
||||
assertSame("Wrong or no parent set on table", schema, table.getParent());
|
||||
assertEquals("node", table.getName());
|
||||
assertEquals(3, table.getColumns().size());
|
||||
|
||||
assertSame("Wrong or no parent set", table, table.getColumns().get(0).getParent());
|
||||
assertEquals("id", table.getColumns().get(0).getName());
|
||||
assertEquals("NUMBER(10)", table.getColumns().get(0).getType());
|
||||
assertEquals(false, table.getColumns().get(0).isNullable());
|
||||
|
||||
assertSame("Wrong or no parent set", table, table.getColumns().get(1).getParent());
|
||||
assertEquals("nodeRef", table.getColumns().get(1).getName());
|
||||
assertEquals("VARCHAR2(200)", table.getColumns().get(1).getType());
|
||||
assertEquals(false, table.getColumns().get(1).isNullable());
|
||||
|
||||
assertSame("Wrong or no parent set", table, table.getColumns().get(2).getParent());
|
||||
assertEquals("name", table.getColumns().get(2).getName());
|
||||
assertEquals("VARCHAR2(150)", table.getColumns().get(2).getType());
|
||||
assertEquals(true, table.getColumns().get(2).isNullable());
|
||||
|
||||
assertSame("Wrong or no parent set", table, table.getPrimaryKey().getParent());
|
||||
assertEquals("pk_node", table.getPrimaryKey().getName());
|
||||
assertEquals(1, table.getPrimaryKey().getColumnNames().size());
|
||||
assertEquals("id", table.getPrimaryKey().getColumnNames().get(0));
|
||||
|
||||
assertEquals(1, table.getForeignKeys().size());
|
||||
assertSame("Wrong or no parent set", table, table.getForeignKeys().get(0).getParent());
|
||||
assertEquals("fk_node_noderef", table.getForeignKeys().get(0).getName());
|
||||
assertEquals("nodeRef", table.getForeignKeys().get(0).getLocalColumn());
|
||||
assertEquals("node", table.getForeignKeys().get(0).getTargetTable());
|
||||
@ -93,20 +102,29 @@ public class XMLToSchemaTest
|
||||
|
||||
assertEquals(1, table.getIndexes().size());
|
||||
Index index = table.getIndexes().get(0);
|
||||
assertSame("Wrong or no parent set on index", table, index.getParent());
|
||||
assertEquals("idx_node_by_id", index.getName());
|
||||
assertEquals(true, index.isUnique());
|
||||
assertEquals(2, index.getColumnNames().size());
|
||||
assertEquals("id", index.getColumnNames().get(0));
|
||||
assertEquals("nodeRef", index.getColumnNames().get(1));
|
||||
assertEquals(1, index.getValidators().size());
|
||||
DbValidator<? extends DbObject> validator = index.getValidators().get(0);
|
||||
DbValidator validator = index.getValidators().get(0);
|
||||
assertEquals(NameValidator.class, validator.getClass());
|
||||
assertEquals(1, validator.getPropertyNames().size());
|
||||
assertEquals("idx_.+", validator.getProperty("pattern"));
|
||||
|
||||
assertEquals("node_seq", ((Sequence) objects.next()).getName());
|
||||
assertEquals("person_seq", ((Sequence) objects.next()).getName());
|
||||
assertEquals("content_seq", ((Sequence) objects.next()).getName());
|
||||
Sequence seq = (Sequence) objects.next();
|
||||
assertSame("Wrong or no parent set", schema, seq.getParent());
|
||||
assertEquals("node_seq", seq.getName());
|
||||
|
||||
seq = (Sequence) objects.next();
|
||||
assertSame("Wrong or no parent set", schema, seq.getParent());
|
||||
assertEquals("person_seq", seq.getName());
|
||||
|
||||
seq = (Sequence) objects.next();
|
||||
assertSame("Wrong or no parent set", schema, seq.getParent());
|
||||
assertEquals("content_seq", seq.getName());
|
||||
|
||||
assertFalse("Should be no more DB objects", objects.hasNext());
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public abstract class AbstractDbObject implements DbObject
|
||||
/** How differences in the name field should be reported */
|
||||
private Strength nameStrength = Strength.ERROR;
|
||||
protected ComparisonUtils comparisonUtils = new DefaultComparisonUtils();
|
||||
private List<DbValidator<?>> validators = new ArrayList<DbValidator<?>>();
|
||||
private List<DbValidator> validators = new ArrayList<DbValidator>();
|
||||
|
||||
|
||||
/**
|
||||
@ -212,7 +212,7 @@ public abstract class AbstractDbObject implements DbObject
|
||||
|
||||
|
||||
@Override
|
||||
public List<DbValidator<? extends DbObject>> getValidators()
|
||||
public List<DbValidator> getValidators()
|
||||
{
|
||||
return validators;
|
||||
}
|
||||
@ -222,7 +222,7 @@ public abstract class AbstractDbObject implements DbObject
|
||||
* @param validators the validators to set
|
||||
*/
|
||||
@Override
|
||||
public void setValidators(List<DbValidator<? extends DbObject>> validators)
|
||||
public void setValidators(List<DbValidator> validators)
|
||||
{
|
||||
if (validators == null)
|
||||
{
|
||||
|
@ -113,11 +113,10 @@ public class AbstractDbObjectTest
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void canGetValidators()
|
||||
{
|
||||
List<DbValidator<? extends DbObject>> validators = dbObject.getValidators();
|
||||
List<DbValidator> validators = dbObject.getValidators();
|
||||
assertEquals(0, validators.size());
|
||||
|
||||
dbObject.setValidators(null);
|
||||
@ -166,13 +165,13 @@ public class AbstractDbObjectTest
|
||||
}
|
||||
|
||||
|
||||
private List<DbValidator<? extends DbObject>> validatorList(DbValidator<? extends DbObject>... validators)
|
||||
private List<DbValidator> validatorList(DbValidator... validators)
|
||||
{
|
||||
return Arrays.asList(validators);
|
||||
}
|
||||
|
||||
|
||||
private static class TestValidator extends AbstractDbValidator<DbObject>
|
||||
private static class TestValidator extends AbstractDbValidator
|
||||
{
|
||||
@Override
|
||||
public void validate(DbObject reference, DbObject target, DiffContext ctx)
|
||||
|
@ -18,13 +18,12 @@
|
||||
*/
|
||||
package org.alfresco.util.schemacomp.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.util.schemacomp.DbObjectVisitor;
|
||||
import org.alfresco.util.schemacomp.DiffContext;
|
||||
import org.alfresco.util.schemacomp.Results;
|
||||
import org.alfresco.util.schemacomp.Result.Strength;
|
||||
import org.alfresco.util.schemacomp.Results;
|
||||
import org.alfresco.util.schemacomp.validator.DbValidator;
|
||||
|
||||
/**
|
||||
@ -98,12 +97,12 @@ public interface DbObject
|
||||
* @see DbValidator
|
||||
* @return DbValidator List
|
||||
*/
|
||||
List<DbValidator<? extends DbObject>> getValidators();
|
||||
List<DbValidator> getValidators();
|
||||
|
||||
/**
|
||||
* Set/override the validators associated with this database object.
|
||||
*
|
||||
* @param validators
|
||||
*/
|
||||
void setValidators(List<DbValidator<? extends DbObject>> validators);
|
||||
void setValidators(List<DbValidator> validators);
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import org.alfresco.util.schemacomp.DbObjectVisitor;
|
||||
import org.alfresco.util.schemacomp.DbProperty;
|
||||
import org.alfresco.util.schemacomp.DiffContext;
|
||||
import org.alfresco.util.schemacomp.Result.Strength;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Represents an index on a table.
|
||||
@ -35,6 +37,7 @@ public class Index extends AbstractDbObject
|
||||
{
|
||||
private final List<String> columnNames = new ArrayList<String>();
|
||||
private boolean unique;
|
||||
private static Log logger = LogFactory.getLog(Index.class);
|
||||
|
||||
public Index(String name)
|
||||
{
|
||||
|
@ -22,14 +22,12 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.util.schemacomp.model.DbObject;
|
||||
|
||||
/**
|
||||
* Base class providing DbValidator support.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public abstract class AbstractDbValidator<T extends DbObject> implements DbValidator<T>
|
||||
public abstract class AbstractDbValidator implements DbValidator
|
||||
{
|
||||
private final Map<String, String> properties = new HashMap<String, String>();
|
||||
|
||||
|
@ -29,9 +29,9 @@ import org.alfresco.util.schemacomp.model.DbObject;
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public interface DbValidator<T extends DbObject>
|
||||
public interface DbValidator
|
||||
{
|
||||
void validate(T reference, T target, DiffContext ctx);
|
||||
void validate(DbObject reference, DbObject target, DiffContext ctx);
|
||||
|
||||
void setProperty(String name, String value);
|
||||
|
||||
|
@ -36,7 +36,7 @@ import org.hibernate.dialect.Dialect;
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class NameValidator implements DbValidator<DbObject>
|
||||
public class NameValidator implements DbValidator
|
||||
{
|
||||
private Pattern pattern;
|
||||
|
||||
|
@ -22,10 +22,7 @@ package org.alfresco.util.schemacomp.validator;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.util.schemacomp.DiffContext;
|
||||
|
@ -26,7 +26,7 @@ import org.alfresco.util.schemacomp.model.DbObject;
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class NullValidator extends AbstractDbValidator<DbObject>
|
||||
public class NullValidator extends AbstractDbValidator
|
||||
{
|
||||
@Override
|
||||
public void validate(DbObject reference, DbObject target, DiffContext ctx)
|
||||
|
Loading…
x
Reference in New Issue
Block a user