// ============================================================================
//
// Copyright (C) 2006-2012 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.core.model.metadata;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.log4j.Logger;
import org.talend.commons.exception.SystemException;
import org.talend.commons.xml.XmlNodeRetriever;
import org.talend.core.language.ECodeLanguage;
import org.talend.core.model.metadata.types.DBTypeUtil;
import org.talend.core.model.metadata.types.JavaType;
import org.talend.core.model.metadata.types.JavaTypesManager;
import org.talend.core.runtime.i18n.Messages;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* DOC amaumont class global comment. Detailled comment <br/>
*
*/
public class MappingFileLoader {
private static Logger log = Logger.getLogger(MappingFileLoader.class);
private Dbms dbms;
/**
* DOC amaumont Comment method "load".
*
* @param file
* @throws SystemException
*/
public void load(File file) throws SystemException {
XmlNodeRetriever defaultNodeRetriever = new XmlNodeRetriever();
ECodeLanguage codeLanguage = MetadataTalendType.getCodeLanguage();
Set<String> hAllTalendTypes = new HashSet<String>();
if (codeLanguage == ECodeLanguage.JAVA) {
JavaType[] javaTypes = JavaTypesManager.getJavaTypes();
for (JavaType javaType : javaTypes) {
hAllTalendTypes.add(javaType.getId());
}
} else if (codeLanguage == ECodeLanguage.PERL) {
String[] perlTypes = MetadataTalendType.getPerlTypes();
for (String perlType : perlTypes) {
hAllTalendTypes.add(perlType);
}
} else {
throw new IllegalStateException("Case language not found"); //$NON-NLS-1$
}
StringBuffer stringBuff = new StringBuffer();
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder analyser = documentBuilderFactory.newDocumentBuilder();
Document document = analyser.parse(file);
stringBuff.append("language=" + codeLanguage + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
stringBuff.append("file=" + file + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
NodeList dbmsNodes = document.getElementsByTagName("dbms"); //$NON-NLS-1$
for (int iDbms = 0; iDbms < dbmsNodes.getLength(); iDbms++) {
Node dbmsNode = dbmsNodes.item(iDbms);
Set<String> hTalendTypesProcessed = new HashSet<String>(hAllTalendTypes);
NamedNodeMap dbmsAttributes = dbmsNode.getAttributes();
String dbmsProductValue = dbmsAttributes.getNamedItem("product").getNodeValue(); //$NON-NLS-1$
String dbmsIdValue = dbmsAttributes.getNamedItem("id").getNodeValue(); //$NON-NLS-1$
String dbmsLabelValue = dbmsAttributes.getNamedItem("label").getNodeValue(); //$NON-NLS-1$
Node defaultDbmsItem = dbmsAttributes.getNamedItem("default"); //$NON-NLS-1$
boolean defaultDbms = false;
if (defaultDbmsItem != null && "true".equals(defaultDbmsItem.getNodeValue())) { //$NON-NLS-1$
defaultDbms = true;
}
dbms = new Dbms(dbmsIdValue);
dbms.setLabel(dbmsLabelValue);
dbms.setProduct(dbmsProductValue);
dbms.setDefaultDbms(defaultDbms);
boolean dbmsOverwriteExisting = !MetadataTalendType.getDbmsSet().add(dbms);
if (dbmsOverwriteExisting) {
log.warn(Messages.getString("MappingFileLoader.DbmsIdAlreadyExists", new Object[] { dbmsIdValue })); //$NON-NLS-1$
}
// list all dbms children nodes
List<Node> childrenOfDbmsNode = getChildElementNodes(dbmsNode);
// TODO create a dtd
// search "dbTypes" node
Node dbTypesNode = childrenOfDbmsNode.get(0);
Set<String> hAllDbTypes = new HashSet<String>();
// search and load "dbTypes/dbType" nodes
// search and load ignoreLength and ignorePrecision nodes
// search and load preBeforelen nodes
ArrayList<String> dbTypes = new ArrayList<String>();
ArrayList<DbDefaultLengthAndPrecision> dbDefault = new ArrayList<DbDefaultLengthAndPrecision>();
ArrayList<DbIgnoreLengthAndPrecision> dbIgnore = new ArrayList<DbIgnoreLengthAndPrecision>();
ArrayList<DbPreBeforeLength> dbPbeforeLList = new ArrayList<DbPreBeforeLength>();
dbms.setDbmsTypes(dbTypes);
dbms.setDefaultLengthPrecision(dbDefault);
dbms.setIgnoreLengthPrecision(dbIgnore);
dbms.setPrebeforelength(dbPbeforeLList);
List<Node> typeNodes = getChildElementNodes(dbTypesNode);
for (Node typeNode : typeNodes) {
NamedNodeMap typeNodeAtttributes = typeNode.getAttributes();
String typeValue = typeNodeAtttributes.getNamedItem("type").getNodeValue(); //$NON-NLS-1$
stringBuff.append("typeValue=" + typeValue + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
Node defaultTypeItem = typeNodeAtttributes.getNamedItem("default"); //$NON-NLS-1$
if (hAllDbTypes.contains(typeValue)) {
String message = Messages
.getString(
"MappingFileLoader.DbTypeAlreadyExists", new Object[] { dbmsIdValue, typeValue, file.getName(), defaultNodeRetriever.getAbsoluteXPathFromNode(typeNode) });//$NON-NLS-1$
log.warn(message);
continue;
}
dbTypes.add(typeValue);
hAllDbTypes.add(typeValue);
DbDefaultLengthAndPrecision dbDefaultLP = new DbDefaultLengthAndPrecision();
DbIgnoreLengthAndPrecision dbIgnoreLP = new DbIgnoreLengthAndPrecision();
DbPreBeforeLength dbPBeforeL = new DbPreBeforeLength();
// default length and precision
Node defaultLengthItem = typeNodeAtttributes.getNamedItem("defaultLength"); //$NON-NLS-1$
Node defaultPrecision = typeNodeAtttributes.getNamedItem("defaultPrecision"); //$NON-NLS-1$
if (defaultLengthItem != null)
dbDefaultLP.setDefaultLength(Integer.parseInt(defaultLengthItem.getNodeValue()));
if (defaultPrecision != null)
dbDefaultLP.setDefaultPrecision(Integer.parseInt(defaultPrecision.getNodeValue()));
dbDefaultLP.setDbTypeName(typeValue);
dbDefault.add(dbDefaultLP);
// ignore Length and Precision
Node ignoreLength = typeNodeAtttributes.getNamedItem("ignoreLen"); //$NON-NLS-1$
Node ignorePrecision = typeNodeAtttributes.getNamedItem("ignorePre"); //$NON-NLS-1$
if (ignoreLength != null)
dbIgnoreLP.setIgnoreLength(ignoreLength.getNodeValue());
if (ignorePrecision != null)
dbIgnoreLP.setIgnorePrecision(ignorePrecision.getNodeValue());
dbIgnoreLP.setDbType(typeValue);
dbIgnore.add(dbIgnoreLP);
// Precision before Length
Node preBeforelen = typeNodeAtttributes.getNamedItem("preBeforelen"); //$NON-NLS-1$
if (preBeforelen != null)
dbPBeforeL.setPreBeforeLen(preBeforelen.getNodeValue());
dbPBeforeL.setDbType(typeValue);
dbPbeforeLList.add(dbPBeforeL);
if (defaultTypeItem != null && "true".equals(defaultTypeItem.getNodeValue())) { //$NON-NLS-1$
dbms.setDefaultDbType(typeValue);
}
}
Set<String> hDbTypesProcessed = new HashSet<String>(hAllDbTypes);
// search and load "language/type" nodes
List<Node> languageNodes = childrenOfDbmsNode.subList(1, childrenOfDbmsNode.size());
for (int i = 0; i < languageNodes.size(); i++) {
Node languageNode = languageNodes.get(i);
String languageValue = languageNode.getAttributes().getNamedItem("name").getNodeValue(); //$NON-NLS-1$
if (codeLanguage.getName().equalsIgnoreCase(languageValue)) {
List<Node> mappingDirections = getChildElementNodes(languageNode);
Node talendTypesToDbTypesNode = mappingDirections.get(0);
Set<MappingType> mappingTypes = new HashSet<MappingType>();
dbms.setTalendToDbTypes(mappingTypes);
List<Node> talendTypeSourcesList = getChildElementNodes(talendTypesToDbTypesNode);
int talendTypeSourcesListListSize = talendTypeSourcesList.size();
for (int iTalendTypeSource = 0; iTalendTypeSource < talendTypeSourcesListListSize; iTalendTypeSource++) {
Node talendTypeSource = talendTypeSourcesList.get(iTalendTypeSource);
NamedNodeMap talendTypeAttributes = talendTypeSource.getAttributes();
Node talendTypeItem = talendTypeAttributes.getNamedItem("type"); //$NON-NLS-1$
if (talendTypeItem == null) {
continue;
}
String talendType = talendTypeItem.getNodeValue();
stringBuff.append("talendTypeItem=" + talendType + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
if (!hAllTalendTypes.contains(talendType)) { // test
// if
// the
// type
// exists
String message = Messages.getString(
"MappingFileLoader.InvalidTalendType", //$NON-NLS-1$
new Object[] { talendType, codeLanguage.getName(), dbmsIdValue,
defaultNodeRetriever.getAbsoluteXPathFromNode(talendTypeSource) });
// System.out.println(message);
log.warn(message);
continue;
}
hTalendTypesProcessed.remove(talendType);
List<Node> languageTypesNodes = getChildElementNodes(talendTypeSource);
for (int j = 0; j < languageTypesNodes.size(); j++) {
Node languageTypeNode = languageTypesNodes.get(j);
NamedNodeMap dbTypeAttributes = languageTypeNode.getAttributes();
Node dbTypeItem = dbTypeAttributes.getNamedItem("type"); //$NON-NLS-1$
if (dbTypeItem == null) {
continue;
}
String dbType = dbTypeItem.getNodeValue();
if (!hAllDbTypes.contains(dbType)) {
String message = Messages
.getString(
"MappingFileLoader.UndeclaredDbType", new Object[] { dbType, dbmsIdValue, defaultNodeRetriever.getAbsoluteXPathFromNode(languageTypeNode) }); //$NON-NLS-1$
// System.out.println(message);
log.warn(message);
continue;
}
Node defaultSelectedItem = dbTypeAttributes.getNamedItem("default"); //$NON-NLS-1$
MappingType objectMappingType = new MappingType();
objectMappingType.setTalendType(talendType);
objectMappingType.setDbType(dbType);
objectMappingType
.setDefaultSelected(defaultSelectedItem != null
&& defaultSelectedItem.getNodeValue().equalsIgnoreCase("true") ? Boolean.TRUE : Boolean.FALSE); //$NON-NLS-1$
mappingTypes.add(objectMappingType);
}
}
Node dbToTalendTypes = mappingDirections.get(1);
mappingTypes = new HashSet<MappingType>();
dbms.setDbToTalendTypes(mappingTypes);
List<Node> dbTypeSourcesList = getChildElementNodes(dbToTalendTypes);
int dbTypeSourcesListListSize = dbTypeSourcesList.size();
for (int iDbTypeSource = 0; iDbTypeSource < dbTypeSourcesListListSize; iDbTypeSource++) {
Node dbTypeSource = dbTypeSourcesList.get(iDbTypeSource);
NamedNodeMap dbTypeAttributes = dbTypeSource.getAttributes();
Node dbTypeItem = dbTypeAttributes.getNamedItem("type"); //$NON-NLS-1$
if (dbTypeItem == null) {
continue;
}
String dbType = dbTypeItem.getNodeValue();
stringBuff.append("dbType=" + dbType + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
if (!hAllDbTypes.contains(dbType)) {
String message = Messages
.getString(
"MappingFileLoader.UndeclaredDbType", new Object[] { dbType, dbmsIdValue, defaultNodeRetriever.getAbsoluteXPathFromNode(dbTypeSource) }); //$NON-NLS-1$
// System.out.println(message);
log.warn(message);
continue;
}
hDbTypesProcessed.remove(dbType);
// System.out.println("Removed :" + dbType);
List<Node> languageTypesNodes = getChildElementNodes(dbTypeSource);
for (int j = 0; j < languageTypesNodes.size(); j++) {
Node languageTypeNode = languageTypesNodes.get(j);
NamedNodeMap talendTypeAttributes = languageTypeNode.getAttributes();
Node talendTypeItem = talendTypeAttributes.getNamedItem("type"); //$NON-NLS-1$
if (talendTypeItem == null) {
continue;
}
String talendType = talendTypeItem.getNodeValue();
if (!hAllTalendTypes.contains(talendType)) {
String message = Messages.getString(
"MappingFileLoader.InvalidTalendType", //$NON-NLS-1$
new Object[] { talendType, codeLanguage.getName(), dbmsIdValue,
defaultNodeRetriever.getAbsoluteXPathFromNode(languageTypeNode) });
// System.out.println(message);
log.warn(message);
continue;
}
Node defaultSelectedItem = talendTypeAttributes.getNamedItem("default"); //$NON-NLS-1$
boolean defaultSelected = defaultSelectedItem != null
&& defaultSelectedItem.getNodeValue().equalsIgnoreCase("true") ? true : false; //$NON-NLS-1$
MappingType mappingType = new MappingType();
mappingType.setDbType(dbType);
mappingType.setTalendType(talendType);
mappingType.setDefaultSelected(defaultSelected);
mappingTypes.add(mappingType);
}
}
}
}
if (hTalendTypesProcessed.size() > 0) {
Map<String, Map<String, List<DBTypeUtil>>> javaTypeMappingFromExtension = JavaTypesManager
.getJavaTypeMappingFromExtension();
Iterator<String> iterator = hTalendTypesProcessed.iterator();
while (iterator.hasNext()) {
String talendType = iterator.next();
Map<String, List<DBTypeUtil>> dbAndDBType = javaTypeMappingFromExtension.get(talendType);
if (dbAndDBType != null) {
// remove talend type if from extension
iterator.remove();
List<DBTypeUtil> dBTypeUtils = dbAndDBType.get(dbms.getId());
Set<MappingType> talendToDbTypes = dbms.getTalendToDbTypes();
Set<MappingType> dbToTalendTypes = dbms.getDbToTalendTypes();
if (dBTypeUtils != null && !dBTypeUtils.isEmpty()) {
for (DBTypeUtil dbType : dBTypeUtils) {
MappingType mappingType = new MappingType();
mappingType.setDbType(dbType.getDbTypeName());
mappingType.setTalendType(talendType);
mappingType.setDefaultSelected(dbType.isDefault());
talendToDbTypes.add(mappingType);
mappingType = new MappingType();
mappingType.setDbType(dbType.getDbTypeName());
mappingType.setTalendType(talendType);
// user added talend type won't be the default mapping type to dbtype
mappingType.setDefaultSelected(false);
dbToTalendTypes.add(mappingType);
}
}
}
}
}
if (hDbTypesProcessed.size() > 0) {
String dbTypesStr = ""; //$NON-NLS-1$
for (String dbType : hDbTypesProcessed) {
dbTypesStr += "\n" + dbType; //$NON-NLS-1$
}
String message = Messages
.getString(
"MappingFileLoader.UnbindedDbTypes", new Object[] { dbmsIdValue, codeLanguage.getName(), dbTypesStr }); //$NON-NLS-1$
// System.out.println(message);
log.warn(message);
}
if (hTalendTypesProcessed.size() > 0) {
String talendTypesStr = ""; //$NON-NLS-1$
for (String talendType : hTalendTypesProcessed) {
talendTypesStr += "\n" + talendType; //$NON-NLS-1$
}
String message = Messages
.getString(
"MappingFileLoader.UnbindedTalendTypes", new Object[] { dbmsIdValue, codeLanguage.getName(), talendTypesStr }); //$NON-NLS-1$
// System.out.println(message);
log.warn(message);
}
}
} catch (Exception e) {
throw new SystemException("Error when load db mapping, lasted loaded data are:\n" + stringBuff.toString()); //$NON-NLS-1$
}
}
/**
* Get children of type ELEMENT_NODE from parent <code>parentNode</code>.
*
* @param parentNode
* @return
*/
private List<Node> getChildElementNodes(Node parentNode) {
Node childNode = parentNode.getFirstChild();
ArrayList<Node> list = new ArrayList<Node>();
while (childNode != null) {
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
list.add(childNode);
}
childNode = childNode.getNextSibling();
}
return list;
}
}