/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.esl.sql.model; import java.io.InputStream; import java.util.List; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import com.enonic.esl.sql.model.datatypes.DataType; /** * This class implements the loading of database model. */ public final class DatabaseXMLFactory { /** * Generate table. */ private static Table generateTable( Element current ) { String tableName = current.getAttributeValue( "name" ); String elementName = current.getAttributeValue( "elementname" ); String parentName = current.getAttributeValue( "parentname" ); Table table = new Table( tableName, elementName, parentName ); List list = current.getChildren(); for ( Object child : list ) { Element childElement = (Element) child; if ( childElement.getName().equals( "column" ) ) { Column column = generateColumn( childElement ); table.addColumn( column ); } else if ( childElement.getName().equals( "foreign-key" ) ) { ForeignKeyColumn fkColumn = generateForeignKeyColumn( childElement ); table.addColumn( fkColumn ); } } return table; } /** * Generate column. */ private static Column generateColumn( Element current ) { String xpath = current.getAttributeValue( "xpath" ); boolean required = Boolean.valueOf( current.getAttributeValue( "required" ) ); boolean primaryKey = Boolean.valueOf( current.getAttributeValue( "primaryKey" ) ); String typeStr = current.getAttributeValue( "type" ); DataType type = Constants.getType( typeStr ); int size = Integer.parseInt( current.getAttributeValue( "size", "-1" ) ); String columnName = current.getAttributeValue( "name" ); return new Column( columnName, xpath, required, primaryKey, type, size ); } /** * Generate foreign key. */ private static ForeignKeyColumn generateForeignKeyColumn( Element current ) { String xpath = current.getAttributeValue( "xpath" ); boolean required = Boolean.valueOf( current.getAttributeValue( "required" ) ); boolean primaryKey = Boolean.valueOf( current.getAttributeValue( "primaryKey" ) ); String typeStr = current.getAttributeValue( "type" ); DataType type = Constants.getType( typeStr ); // <foreign-key> elements Element referenceElem = current.getChild( "reference" ); String columnName = referenceElem.getAttributeValue( "local" ); String defaultValue = current.getAttributeValue( "defaultValue" ); String referencedTableName = current.getAttributeValue( "foreignTable" ); String referencedColumnName = referenceElem.getAttributeValue( "foreign" ); boolean isDelete = "true".equals( current.getAttributeValue( "delete" ) ); return new ForeignKeyColumn( columnName, xpath, required, primaryKey, type, defaultValue, referencedTableName, referencedColumnName, isDelete, -1 ); } /** * Generate real foreign key. */ private static ForeignKey generateRealForeignKey( Element current, Database database ) { String tableName = current.getParentElement().getAttributeValue( "name" ); Table table = database.getTable( tableName ); String foreignKeyName = current.getAttributeValue( "name" ); String foreignTableName = current.getAttributeValue( "foreignTable" ); Table foreignTable = database.getTable( foreignTableName ); ForeignKey foreignKey = new ForeignKey( foreignKeyName, foreignTable ); List columns = current.getChildren( "column" ); for ( Object child : columns ) { Element childElement = (Element) child; String columnName = childElement.getAttributeValue( "name" ); String foreignColumnName = childElement.getAttributeValue( "foreignColumn" ); Column column = table.getColumn( columnName ); Column foreignColumn = foreignTable.getColumn( foreignColumnName ); foreignKey.addReference( column, foreignColumn ); } return foreignKey; } /** * Generate index. */ private static Index generateIndex( Element current, Table table ) { String indexName = current.getAttributeValue( "name" ); Index index = new Index( indexName ); index.setUnique( Boolean.valueOf( current.getAttributeValue( "unique" ) ) ); List columns = current.getChildren( "column" ); for ( Object child : columns ) { Element childElement = (Element) child; String columnName = childElement.getAttributeValue( "name" ); Column column = table.getColumn( columnName ); index.addColumn( column ); } return index; } /** * Generate view. */ private static View generateView( Element current ) { String viewName = current.getAttributeValue( "name" ); String elementName = current.getAttributeValue( "elementname" ); String parentName = current.getAttributeValue( "parentname" ); String selectSql = current.getChildText( "selectsql" ); View view = new View( viewName, elementName, parentName, selectSql ); List columns = current.getChildren( "column" ); for ( Object child : columns ) { Element childElement = (Element) child; Column column = generateColumn( childElement ); view.addColumn( column ); } return view; } /** * Generate database. */ private static Database generateDatabase( Document doc ) { Element docElem = doc.getRootElement(); String name = docElem.getAttributeValue( "name" ); int version = Integer.parseInt( docElem.getAttributeValue( "version" ) ); Database database = new Database( name, version ); // <table..> List children = docElem.getChildren( "table" ); for ( Object child : children ) { database.addTable( generateTable( (Element) child ) ); } // <view..> children = docElem.getChildren( "view" ); for ( Object child : children ) { database.addView( generateView( (Element) child ) ); } // <statement..> children = docElem.getChildren( "statement" ); for ( Object child : children ) { database.addStatement( ( (Element) child ).getText() ); } // foreign keys and indexes children = docElem.getChildren( "table" ); for ( Object child : children ) { String tableName = ( (Element) child ).getAttributeValue( "name" ); Table table = database.getTable( tableName ); for ( Object item : ( (Element) child ).getChildren( "foreignkey" ) ) { Element foreignKeyElem = (Element) item; ForeignKey foreignKey = generateRealForeignKey( foreignKeyElem, database ); table.addRealForeignKey( foreignKey ); } for ( Object item : ( (Element) child ).getChildren( "index" ) ) { Element indexElem = (Element) item; Index index = generateIndex( indexElem, table ); table.addIndex( index ); } } database.setDatabaseMappings(); return database; } /** * Generate database. */ public static Database generateDatabase( InputStream doc ) throws Exception { SAXBuilder builder = new SAXBuilder(); return generateDatabase( builder.build( doc ) ); } }