/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.xmlcode;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XMLMapId {
private Vector _mapEntryList;
private String _description;
public XMLMapId(Node mapIdNode, XMLMapping anXMLMapping) throws InvalidModelException {
super();
Node tempAttribute;
NamedNodeMap attributes;
NodeList propertiesNodeList;
Node tempNode;
if (!mapIdNode.getNodeName().equals(XMLMapping.mapIdLabel)) {
throw new InvalidModelException("Invalid tag '" + mapIdNode.getNodeName() + "' found in model file");
}
attributes = mapIdNode.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
tempAttribute = attributes.item(i);
/*if (tempAttribute.getNodeName().equals(XMLMapping.nameLabel)) {
nameIsSpecified = true;
name = tempAttribute.getNodeValue();
} else {
throw new InvalidModelException("Invalid attribute '" + tempAttribute.getNodeName() + "' found in model file for tag 'entity'");
}*/
}
_mapEntryList = new Vector();
propertiesNodeList = mapIdNode.getChildNodes();
for (int i = 0; i < propertiesNodeList.getLength(); i++) {
tempNode = propertiesNodeList.item(i);
if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
if (tempNode.getNodeName().equals(XMLMapping.descriptionLabel)) {
if (tempNode.getChildNodes().getLength() == 1 && tempNode.getFirstChild().getNodeType() == Node.TEXT_NODE) {
setDescription(tempNode.getFirstChild().getNodeValue());
// System.out.println("Description = "+getDescription());
}
} else if (tempNode.getNodeName().equals(XMLMapping.mapLabel)) {
MapEntry newMapEntry = new MapEntry(tempNode);
_mapEntryList.add(newMapEntry);
// System.out.println("Register map entry "+newMapEntry.getEntityClass()+" and "+newMapEntry.getKeyValueProperty().getName());
} else {
throw new InvalidModelException("Invalid tag '" + tempNode.getNodeName() + "' found in model file for tag 'entity'");
}
} else if (tempNode.getNodeType() == Node.TEXT_NODE) {
// Non significative text will be simply ignored
if (tempNode.getNodeValue().trim().length() > 0) {
throw new InvalidModelException("Invalid text found in model file");
}
} else if (tempNode.getNodeType() == Node.ATTRIBUTE_NODE) {
// Simply ignore it
} else if (tempNode.getNodeType() == Node.COMMENT_NODE) {
// Simply ignore it
} else {
throw new InvalidModelException("Invalid xml tag found as child of 'mapId' tag in model file");
}
}
if (_mapEntryList.size() == 0) {
throw new InvalidModelException("No identifier mapping defined");
}
}
public String getDescription() {
return _description;
}
public void setDescription(String description) {
_description = description;
}
public class MapEntry {
private Class entityClass;
private SingleKeyValueProperty keyValueProperty;
private String entityClassName;
private String identifierAccessorName;
public MapEntry(Node mapEntryNode) throws InvalidModelException {
super();
Node tempAttribute;
NamedNodeMap attributes;
if (!mapEntryNode.getNodeName().equals(XMLMapping.mapLabel)) {
throw new InvalidModelException("Invalid tag '" + mapEntryNode.getNodeName() + "' found in model file");
}
attributes = mapEntryNode.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
tempAttribute = attributes.item(i);
if (tempAttribute.getNodeName().equals(XMLMapping.entityClassLabel)) {
entityClassName = tempAttribute.getNodeValue();
} else if (tempAttribute.getNodeName().equals(XMLMapping.identifierAccessorLabel)) {
identifierAccessorName = tempAttribute.getNodeValue();
} else {
throw new InvalidModelException("Invalid attribute '" + tempAttribute.getNodeName()
+ "' found in model file for tag 'entity'");
}
}
try {
entityClass = Class.forName(entityClassName);
} catch (ClassNotFoundException e) {
throw new InvalidModelException("Class " + entityClassName + " not found.");
}
keyValueProperty = new SingleKeyValueProperty(entityClass, identifierAccessorName, false);
}
public Class getEntityClass() {
return entityClass;
}
public SingleKeyValueProperty getKeyValueProperty() {
return keyValueProperty;
}
}
private Hashtable mapEntriesForClass = new Hashtable();
private MapEntry mapEntryForClass(Class aClass) throws NoMapIdEntryException {
MapEntry returned = (MapEntry) mapEntriesForClass.get(aClass);
if (returned == null) {
for (Enumeration en = _mapEntryList.elements(); en.hasMoreElements();) {
MapEntry next = (MapEntry) en.nextElement();
if (next.getEntityClass().isAssignableFrom(aClass)) {
// May match
if (returned == null || returned.getEntityClass().isAssignableFrom(next.getEntityClass())) {
returned = next;
}
}
}
if (returned == null) {
throw new NoMapIdEntryException("Could not find identifier map entry for " + aClass);
}
// System.out.println("MapEntry for "+aClass+" is "+returned);
mapEntriesForClass.put(aClass, returned);
}
return returned;
}
public String getIdentifierAsStringForObject(XMLSerializable object) throws NoMapIdEntryException {
SingleKeyValueProperty kvProperty = mapEntryForClass(object.getClass()).getKeyValueProperty();
return KeyValueDecoder.valueForKey(object, kvProperty, StringEncoder.getDefaultInstance());
}
public String getIdentifierAsStringForObject(XMLSerializable object, StringEncoder stringEncoder) throws NoMapIdEntryException {
SingleKeyValueProperty kvProperty = mapEntryForClass(object.getClass()).getKeyValueProperty();
return KeyValueDecoder.valueForKey(object, kvProperty, stringEncoder);
}
public static class NoMapIdEntryException extends Exception {
public NoMapIdEntryException(String message) {
super(message);
}
}
}