/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.eas.model.store;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.eas.client.AppClient;
import com.eas.client.metadata.Field;
import com.eas.client.metadata.ForeignKeySpec;
import com.eas.client.metadata.Parameter;
import com.eas.client.metadata.PrimaryKeySpec;
import com.eas.core.Utils;
import com.eas.model.Entity;
import com.eas.model.Model;
import com.eas.model.ModelVisitor;
import com.eas.model.ReferenceRelation;
import com.eas.model.Relation;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;
/**
*
* @author mg
*/
public class XmlDom2Model implements ModelVisitor {
protected final static String YES_STRING = "yes";
protected final static String NO_STRING = "no";
// Tags
public static final String DATAMODEL_TAG_NAME = "datamodel";
public static final String DATASOURCE_NAME_ATTR_NAME = "Name";
public static final String DATASOURCE_TITLE_ATTR_NAME = "Title";
public static final String ENTITY_TAG_NAME = "entity";
// public static final String FIELDS_ENTITY_TAG_NAME = "fieldsEntity";
// public static final String PARAMETERS_ENTITY_TAG_NAME =
// "parametersEntity";
public static final String RELATION_TAG_NAME = "relation";
// public static final String LIGHT_RELATION_TAG_NAME = "lightRelation";
public static final String REFERENCE_RELATION_TAG_NAME = "referenceRelation";
// Attributes
public static final String SCALAR_PROP_NAME_ATTR_NAME = "scalarPropertyName";
public static final String COLLECTION_PROP_NAME_ATTR_NAME = "collectionPropertyName";
// public static final String PRIMARY_KEYS_TAG_NAME = "primaryKeys";
// public static final String FOREIGN_KEYS_TAG_NAME = "foreignKeys";
public static final String PRIMARY_KEY_TAG_NAME = "primaryKey";
// public static final String FOREIGN_KEY_TAG_NAME = "foreignKey";
public static final String NAME_ATTR_NAME = "name";
public static final String DESCRIPTION_ATTR_NAME = "description";
public static final String TYPE_ATTR_NAME = "type";
public static final String NULLABLE_ATTR_NAME = "nullable";
public static final String MODE_ATTR_NAME = "parameterMode";
public static final String IS_PK_ATTR_NAME = "isPk";
// public static final String FK_TAG_NAME = "fk";
public static final String SELECTION_FORM_TAG_NAME = "selectionForm";
// public static final String CLASS_HINT_TAG_NAME = "classHint";
public static final String ENTITY_ID_ATTR_NAME = "entityId";
public static final String QUERY_ID_ATTR_NAME = "queryId";
// public static final String ENTITY_TABLE_ALIAS = "tableAlias";
public static final String LEFT_ENTITY_ID_ATTR_NAME = "leftEntityId";
public static final String LEFT_ENTITY_FIELD_ATTR_NAME = "leftEntityFieldName";
public static final String LEFT_ENTITY_PARAMETER_ATTR_NAME = "leftEntityParameterName";
public static final String RIGHT_ENTITY_ID_ATTR_NAME = "rightEntityId";
public static final String RIGHT_ENTITY_FIELD_ATTR_NAME = "rightEntityFieldName";
public static final String RIGHT_ENTITY_PARAMETER_ATTR_NAME = "rightEntityParameterName";
public static final String CONSTRAINT_NAME_ATTR_NAME = NAME_ATTR_NAME;
public static final String CONSTRAINT_FIELD_ATTR_NAME = "field";
public static final String CONSTRAINT_SCHEMA_ATTR_NAME = "schema";
public static final String CONSTRAINT_TABLE_ATTR_NAME = "table";
protected Element rootTag;
protected JavaScriptObject module;
protected Element currentTag;
protected Model model;
protected Collection<Runnable> relationsResolvers = new ArrayList<Runnable>();
public static Model transform(Document aDocument, String aModuleName, JavaScriptObject aTarget) throws Exception {
try {
Element modelElement = aModuleName != null ? findModelElementByBundleName(aDocument.getDocumentElement(), aModuleName) : aDocument.getDocumentElement();
if (modelElement != null) {
XmlDom2Model transformer = new XmlDom2Model(modelElement, aTarget);
Model model = new Model(AppClient.getInstance());
model.accept(transformer);
return model;
} else
return null;
} catch (Exception ex) {
Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
throw ex;
}
}
private static Element findModelElementByBundleName(Element aElement, String aBundleName) {
if (aElement.getTagName().equals("datamodel")) {
return aElement;// the high level code had to do everything in the
// right way
} else {
Node child = aElement.getFirstChild();
while (child != null) {
if (child instanceof Element) {
Element el = (Element) child;
if (el.hasAttribute("bundle-name")) {
String bundleName = el.getAttribute("bundle-name");
if (bundleName.equals(aBundleName)) {
return el;
}
}
}
child = child.getNextSibling();
}
}
return null;
}
protected XmlDom2Model(Element aRootTag, JavaScriptObject aTarget) {
super();
rootTag = aRootTag;
module = aTarget;
}
protected void readModel(Model aModel) throws Exception {
Element el = rootTag;
if (el != null && aModel != null) {
model = aModel;
try {
currentTag = el;
NodeList nl = currentTag.getChildNodes();
if (nl != null && nl.getLength() > 0) {
Element lcurrentTag = currentTag;
try {
for (int i = 0; i < nl.getLength(); i++) {
String nodeName = nl.item(i).getNodeName();
if ("e".equals(nodeName) || ENTITY_TAG_NAME.equals(nodeName)) {
currentTag = (Element) nl.item(i);
Entity entity = new Entity();
entity.accept(this);
} else if ("r".equals(nodeName) || RELATION_TAG_NAME.equals(nodeName)) {
currentTag = (Element) nl.item(i);
Relation relation = new Relation();
relation.accept(this);
} else if ("rr".equals(nodeName) || REFERENCE_RELATION_TAG_NAME.equals(nodeName)) {
currentTag = (Element) nl.item(i);
Relation relation = new ReferenceRelation();
relation.accept(this);
}
}
} finally {
currentTag = lcurrentTag;
}
}
model.validateQueries();
for (Runnable resolver : relationsResolvers) {
resolver.run();
}
model.checkRelationsIntegrity();
} finally {
relationsResolvers = null;
model = null;
}
}
}
protected void readEntity(Entity entity) {
if (entity != null) {
String entityId = Utils.getAttribute(currentTag, "ei", ENTITY_ID_ATTR_NAME, null);
if ("null".equals(entityId)) {
entityId = null;
}
assert entityId != null : "Entity id must present";
entity.setEntityId(entityId);
String queryId = Utils.getAttribute(currentTag, "qi", QUERY_ID_ATTR_NAME, null);
if ("null".equals(queryId)) {
queryId = null;
}
assert queryId != null : "Query id must present";
entity.setQueryName(queryId);
assert model != null;
entity.setModel(model);
model.addEntity(entity);
}
}
@Override
public void visit(Entity entity) {
String name = Utils.getAttribute(currentTag, "n", DATASOURCE_NAME_ATTR_NAME, null);
if (name != null) {
entity.setName(name);
}
String title = Utils.getAttribute(currentTag, "tt", DATASOURCE_TITLE_ATTR_NAME, null);
if (title != null) {
entity.setTitle(title);
}
readEntity(entity);
}
@Override
public void visit(final Relation relation) {
if (relation != null && model != null) {
final String leftEntityId = Utils.getAttribute(currentTag, "lei", LEFT_ENTITY_ID_ATTR_NAME, null);
final String leftFieldName = Utils.getAttribute(currentTag, "lef", LEFT_ENTITY_FIELD_ATTR_NAME, null);
final String leftParameterName = Utils.getAttribute(currentTag, "lep", LEFT_ENTITY_PARAMETER_ATTR_NAME, null);
final String rightEntityId = Utils.getAttribute(currentTag, "rei", RIGHT_ENTITY_ID_ATTR_NAME, null);
final String rightFieldName = Utils.getAttribute(currentTag, "ref", RIGHT_ENTITY_FIELD_ATTR_NAME, null);
final String rightParameterName = Utils.getAttribute(currentTag, "rep", RIGHT_ENTITY_PARAMETER_ATTR_NAME, null);
model.addRelation(relation);
Runnable resolver = new Runnable() {
@Override
public void run() {
try {
Entity lEntity = model.getEntityById(leftEntityId);
if (lEntity != null) {
if (leftParameterName != null && !leftParameterName.isEmpty()) {
relation.setLeftField(lEntity.getQuery().getParameters().get(leftParameterName));
} else if (leftFieldName != null && !leftFieldName.isEmpty()) {
relation.setLeftField(lEntity.getFields().get(leftFieldName));
}
relation.setLeftEntity(lEntity);
lEntity.addOutRelation(relation);
}
Entity rEntity = model.getEntityById(rightEntityId);
if (rEntity != null) {
if (rightParameterName != null && !rightParameterName.isEmpty()) {
relation.setRightField(rEntity.getQuery().getParameters().get(rightParameterName));
} else if (rightFieldName != null && !rightFieldName.isEmpty()) {
relation.setRightField(rEntity.getFields().get(rightFieldName));
}
relation.setRightEntity(rEntity);
rEntity.addInRelation(relation);
}
} catch (Exception ex) {
Logger.getLogger(XmlDom2Model.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
relationsResolvers.add(resolver);
}
}
@Override
public void visit(final ReferenceRelation relation) {
visit((Relation) relation);
String scalarPropertyName = Utils.getAttribute(currentTag, "spn", SCALAR_PROP_NAME_ATTR_NAME, null);
String collectionPropertyName = Utils.getAttribute(currentTag, "cpn", COLLECTION_PROP_NAME_ATTR_NAME, null);
relation.setScalarPropertyName(scalarPropertyName != null ? scalarPropertyName.trim() : null);
relation.setCollectionPropertyName(collectionPropertyName != null ? collectionPropertyName.trim() : null);
}
@Override
public void visit(Field aField) {
try {
String fieldName = Utils.getAttribute(currentTag, "n", NAME_ATTR_NAME, null);
if (fieldName != null) {
aField.setName(fieldName);
}
String fieldDesc = Utils.getAttribute(currentTag, "d", DESCRIPTION_ATTR_NAME, null);
if (fieldDesc != null) {
aField.setDescription(fieldDesc);
}
String fieldType = Utils.getAttribute(currentTag, "t", TYPE_ATTR_NAME, null);
if (fieldType != null) {
aField.setType(fieldType);
}
aField.setNullable(Utils.getBooleanAttribute(currentTag, "nl", NULLABLE_ATTR_NAME, true));
aField.setPk(Utils.getBooleanAttribute(currentTag, "p", IS_PK_ATTR_NAME, false));
if (aField instanceof Parameter) {
((Parameter) aField).setMode(Utils.getIntegerAttribute(currentTag, "pm", MODE_ATTR_NAME, 0/*
* ParameterMetaData
* .
* parameterModeUnknown
*/));
String selectionForm = Utils.getAttribute(currentTag, "sf", SELECTION_FORM_TAG_NAME, null);
if (selectionForm != null && !"null".equals(selectionForm)) {
((Parameter) aField).setSelectionForm(selectionForm);
}
}
Element lcurrentTag = currentTag;
try {
currentTag = Utils.scanForElementByTagName(currentTag, "pr", PRIMARY_KEY_TAG_NAME);
if (currentTag != null) {
PrimaryKeySpec pk = new PrimaryKeySpec();
visit(pk);
ForeignKeySpec fk = new ForeignKeySpec("", "", "", "", ForeignKeySpec.ForeignKeyRule.CASCADE, ForeignKeySpec.ForeignKeyRule.CASCADE, false, pk.getSchema(), pk.getTable(),
pk.getField(), pk.getCName());
aField.setFk(fk);
}
} finally {
currentTag = lcurrentTag;
}
} catch (NumberFormatException ex) {
Logger.getLogger(XmlDom2Model.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void visit(PrimaryKeySpec pk) {
if (pk != null) {
String name = Utils.getAttribute(currentTag, "n", CONSTRAINT_NAME_ATTR_NAME, null);
if (name != null) {
pk.setCName(name);
}
String schema = Utils.getAttribute(currentTag, "s", CONSTRAINT_SCHEMA_ATTR_NAME, null);
if (schema != null) {
pk.setSchema(schema);
}
String table = Utils.getAttribute(currentTag, "tl", CONSTRAINT_TABLE_ATTR_NAME, null);
if (table != null) {
pk.setTable(table);
}
String field = Utils.getAttribute(currentTag, "f", CONSTRAINT_FIELD_ATTR_NAME, null);
if (field != null) {
pk.setField(field);
}
}
}
public static ForeignKeySpec.ForeignKeyRule readForeignKeyRuleAttribute(Element aElement, String aShortName, String aLongName, ForeignKeySpec.ForeignKeyRule defaultValue) {
try {
String attrValue = Utils.getAttribute(aElement, aShortName, aLongName, null);
return attrValue != null ? ForeignKeySpec.ForeignKeyRule.valueOf(attrValue) : defaultValue;
} catch (Exception ex) {
return defaultValue;
}
}
@Override
public void visit(Model aModel) {
try {
readModel(aModel);
} catch (Exception e) {
e.printStackTrace();
}
}
}