package uk.ac.lkl.common.util.restlet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import uk.ac.lkl.common.util.collections.ImmutableTreeNode;
import uk.ac.lkl.common.util.collections.RootlessTree;
import uk.ac.lkl.common.util.collections.TreePath;
import uk.ac.lkl.common.util.reflect.GenericClass;
import uk.ac.lkl.common.util.restlet.client.BasicRequestCreator;
import uk.ac.lkl.common.util.restlet.client.CollectionRequestCreator;
import uk.ac.lkl.common.util.restlet.client.RequestCreator;
public class EntityLayer {
private String name;
private String serverName;
private int serverPort;
// Keep private (rather than extend RootlessTree class) so can limit access
// to it.
// Is immutable.
private RootlessTree<Entity> tree;
private HashMap<String, RequestCreator> requestCreatorMap;
private XMLConverterManager converterManager;
private EntityTypeManager typeManager;
private String handlerPackageName;
private String manipulatorPackageName;
public EntityLayer(String name, String serverName, int serverPort,
EntityTypeManager typeManager, RootlessTree<Entity> tree,
XMLConverterManager converterManager, String handlerPackageName,
String manipulatorPackageName) {
this.name = name;
this.serverName = serverName;
this.serverPort = serverPort;
this.requestCreatorMap = new HashMap<String, RequestCreator>();
// todo: take copy of tree so this class has only access to ref
this.typeManager = typeManager;
this.tree = tree;
initialiseStringEntityMap();
// todo: take copy of this too?
this.converterManager = converterManager;
this.handlerPackageName = handlerPackageName;
this.manipulatorPackageName = manipulatorPackageName;
}
private void initialiseStringEntityMap() {
Iterator<TreePath<Entity>> treePathIterator = tree.treePathIterator();
while (treePathIterator.hasNext()) {
TreePath<Entity> treePath = treePathIterator.next();
RequestCreator requestCreator;
if (treePath.getElement().isCollection()) {
requestCreator = new CollectionRequestCreator(this, treePath);
} else {
requestCreator = new BasicRequestCreator(this, treePath);
}
String stringPath = createStringPath(treePath);
requestCreatorMap.put(stringPath, requestCreator);
}
}
public String getName() {
return name;
}
public Collection<EntityType> getEntityTypes() {
return typeManager.getTypes();
}
public String getHandlerPackageName() {
return handlerPackageName;
}
public String getManipulatorPackageName() {
return manipulatorPackageName;
}
public String getServerName() {
return serverName;
}
public int getServerPort() {
return serverPort;
}
public RequestCreator getRequestCreator(String entityPath) {
RequestCreator requestCreator = requestCreatorMap.get(entityPath);
if (requestCreator == null)
throw new RuntimeRestletException("Unknown path: " + entityPath);
return requestCreator;
}
public TreePath<Entity> getTreePath(String entityPath) throws RestletException {
RequestCreator requestCreator = requestCreatorMap.get(entityPath);
if (requestCreator == null)
throw new RestletException("Unknown path: " + entityPath);
return requestCreator.getTreePath();
}
private String createStringPath(TreePath<Entity> treePath) {
String result = "";
for (int i = 0; i < treePath.size(); i++) {
if (i > 0) {
result += ".";
}
Entity entity = treePath.getElement(i);
result += entity.getName();
}
return result;
}
// todo: shouldn't be needed. Delegate conversion to this class instead
public <T> XMLConverter<T> getConverter(Class<T> entityClass) {
return converterManager.getConverter(GenericClass.getSimple(entityClass));
}
// todo: shouldn't be needed. Delegate conversion to this class instead
public <T> XMLConverter<T> getConverter(GenericClass<T> entityClass) {
return converterManager.getConverter(entityClass);
}
// with this, shouldn't need to make XMLConverterManager public
public <T> XMLConversionContext createXMLConversionContext(EntityMapper mapper) {
return new XMLConversionContext(converterManager, mapper);
}
// convenience
public <T> Element encode(Document document, Class<T> entityClass, T entity, EntityMapper mapper) throws RestletException {
return encode(document, GenericClass.getSimple(entityClass), entity, mapper);
}
public <T> Element encode(Document document, GenericClass<T> entityClass, T entity, EntityMapper mapper) {
XMLConversionContext context = createXMLConversionContext(mapper);
return encode(document, entityClass, entity, context);
}
private <T> Element encode(Document document, GenericClass<T> entityClass, T entity, XMLConversionContext context) {
return context.convertToXML(document, entityClass, entity);
}
public <T> T decode(Class<T> entityClass, Element element, EntityMapper mapper) {
return decode(GenericClass.getSimple(entityClass), element, mapper);
}
public <T> T decode(GenericClass<T> entityClass, Element element, EntityMapper mapper) {
XMLConversionContext context = createXMLConversionContext(mapper);
return context.convertToObject(entityClass, element);
}
public <T> T decode(GenericClass<T> entityClass, Element element, XMLConversionContext context) throws RestletException {
return context.convertToObject(entityClass, element);
}
public Iterator<Entity> iterator() {
return tree.iterator();
}
public Iterator<TreePath<Entity>> treePathIterator() {
return tree.treePathIterator();
}
public Iterator<ImmutableTreeNode<Entity>> immutableTreeNodeIterator() {
return tree.immutableTreeNodeIterator();
}
public String getURIFormat(boolean useLastId, String entityPath) throws RestletException {
TreePath<Entity> treePath = getTreePath(entityPath);
return getURIFormat(useLastId, treePath);
}
public String getURIFormat(boolean useLastId, TreePath<Entity> treePath) {
String format = "";
for (int i = 0; i < treePath.size(); i++) {
Entity entity = treePath.getElement(i);
format += "/";
if (entity.isCollection()) {
String pluralName = entity.getPluralName();
format += pluralName;
if (i != (treePath.size() - 1) || useLastId) {
format += "/%d";
}
} else {
String name = entity.getName();
format += name;
}
}
return format;
}
}
|