Class DataNodeFactory

java.lang.Object
uk.ac.starlink.datanode.factory.DataNodeFactory

public class DataNodeFactory extends Object
Factory class for constructing DataNode objects. Instances of this class can be used to construct a DataNode from a generic input - for instance a String or a File. It tries to find the most appropriate existing object of one of the classes which implements DataNode. The classes it knows about, in rough order of preference, are: The factory will churn out a DataNode object based on the object it is given for construction, the constructors available from the known implementing objects (the above list), and optionally a list of preferences which may be examined and modified using supplied methods.

The factory has a list of DataNodeBuilder objects which it uses to try to construct nodes from any given object, be it a filename, string, XML source, or whatever. The makeDataNode(uk.ac.starlink.datanode.nodes.DataNode, java.lang.Object) method passes the object to each suitable builder to see if it can turn it into a DataNode, and returns the first successful result. Thus the list of DataNodeBuilders and its order determines what kind of DataNode you will get.

There are two types of builder in the list. The first is generated by reflection on a number of DataNode-implementing classes as listed above. These are made out of suitable (one-argument) constructors supplied by those classes. The second type is a special one of type DataNodeBuilder. This is smart and fast and can make clever decisions about what kind of data node a given file should be turned into.

Initially a newly constructed DataNodeFactory has a FileDataNodeBuilder, StringDataNodeBuilder, SourceDataNodeBuilder DocumentDataNodeBuilder and XMLDataNodeBuilder at the head of the list, followed by ones got from constructors of the known DataNode implementations. This means that a file or string will get tackled first by the clever classes, but if that fails it will trawl through all the other possibilities.

Version:
$Id$
Author:
Mark Taylor (Starlink)
  • Constructor Details

    • DataNodeFactory

      public DataNodeFactory()
      Constructs a new factory with a default list of node builders.
    • DataNodeFactory

      public DataNodeFactory(DataNodeFactory orig)
      Copy constructor. Creates a clone of orig which has identical characteristics to it but its own copies of the data structures, so that modifying the resulting factory will not affect the original.
      Parameters:
      orig - the original factory on which to base this one
  • Method Details

    • removeNodeClass

      public void removeNodeClass(Class clazz)
      Ensures that the factory will not generate nodes of a given class. Following this call, calls to makeDataNode(uk.ac.starlink.datanode.nodes.DataNode, java.lang.Object) will not return any nodes of class clazz. Note this does not affect the construction of classes of subtypes of clazz.
      Parameters:
      clazz - the shunned class (presumably a subtype of DataNode)
    • setPreferredClass

      public void setPreferredClass(Class clazz)
      Sets the class you would most like to see generated by this factory. This raises any constructor-based builders for the named class to the head of the builder list, so if it is possible to build a node of this type, that is what subsequent calls of makeDataNode(uk.ac.starlink.datanode.nodes.DataNode, java.lang.Object) will do.
      Parameters:
      clazz - the preferred class (presumably a subtype of DataNode)
    • setDeprecatedClass

      public void setDeprecatedClass(Class clazz)
      Sets the class you would least like to see generated by this factory. Unlike removeNodeClass(java.lang.Class) this does not remove the possibility of this factory producing such a node at all, but it demotes builders which are known to produce this type of node to the bottom of the builder list.
      Parameters:
      clazz - the deprecated class (presumably a subtype of DataNode)
    • getBuilders

      public List getBuilders()
      Returns the list of DataNodeBuilders which this factory uses to construct data nodes. This may be modified by code which reckons it knows what it's doing, but beware that by modifying this list in strange ways the behaviour of this factory may be compromised. In particular, don't put anything in here which is not a DataNodeBuilder object.
      Returns:
      a mutable list of DataNodeBuilder objects
    • makeDataNode

      public DataNode makeDataNode(DataNode parent, Object obj) throws NoSuchDataException
      Generates a new DataNode from a given object. It goes through this factory's list of builder objects and tries each one with the given object until one of the builders can turn it into a DataNode.

      Ideally, all data node construction (except perhaps the root of a tree) should be done using this method, since it keeps track of various data structures which invoking constructors directly may not.

      Parameters:
      parent - the DataNode whose child the new node will be in the node hierarchy. May be null for a hierarchy root
      obj - an object which is to be turned into a DataNode by one of the builders
      Returns:
      a new DataNode object based on obj
      Throws:
      NoSuchDataException - if none of the builders in the list could turn obj into a DataNode
    • configureDataNode

      public void configureDataNode(DataNode node, DataNode parentNode, Object obj)
      Performs some of the desirable configuration on a new DataNode which is about to get inserted into the tree. This method is called by makeDataNode(uk.ac.starlink.datanode.nodes.DataNode, java.lang.Object) and in most cases should not be called by nodes creating children. However, if a node is creating children other than using makeDataNode (for instance because their constructors are not suitable for the generic node creation system on which this class is based) then this method should be called on the new child before it is returned from the child iterator. Configuring new-born nodes using this method is not essential, but it is likely to ensure that the node is as far as possible a well-behaved member of the node tree; not doing it can lead to some impairment of functionality for the nodes in question.
      Parameters:
      node - the new node to configure
      parentNode - node's parent data node (may be null) if it's at the top of the tree)
      obj - the object on which node is based (may be null) if nothing suitable applies
    • makeErrorDataNode

      public DataNode makeErrorDataNode(DataNode parent, Throwable th)
      Makes a DataNode from a Throwable. This behaves the same as makeDataNode but for convenience it doesn't throw a NoSuchDataException, since it can guarantee to make a DataNode from the throwable.
      Parameters:
      parent - the DataNode whose child this is
      th - the Throwable object from which to construct the node
      Returns:
      a DataNode (probably an ErrorDataNode) representing th
    • makeChildNode

      public DataNode makeChildNode(DataNode parent, Object obj)
      Convenience method which invokes makeDataNode(uk.ac.starlink.datanode.nodes.DataNode, java.lang.Object) but does not throw a NoSuchDataException. If the node construction fails, then makeErrorDataNode(uk.ac.starlink.datanode.nodes.DataNode, java.lang.Throwable) will be called to construct the node for return instead.
      Parameters:
      parent - the DataNode whose child the new node will be in the node hierarchy. May be null for a hierarchy root
      obj - an object which is to be turned into a DataNode by one of the builders
      Returns:
      a new DataNode object based on obj
    • fillInAncestors

      public void fillInAncestors(DataNode node)
      Sets the CreationState of a datanode and its ancestors. The node is queried for its parent object, and a new datanode is made out of this and inserted into the CreationState as its parent. The same is recursively done to the parent, until there is no parent object or node creation fails.
      Parameters:
      node - node whose ancestors are to be filled in
    • getDebug

      public boolean getDebug()
      Indicates whether this factory is running in debug mode.
      Returns:
      debug mode flag
    • setDebug

      public void setDebug(boolean debug)
      Sets whether this factory is running in debug mode.
      Parameters:
      debug - debug mode flag
    • toString

      public String toString()
      Returns a string representation of this factory. The returned string is a comprehensive list of which constructors will be tried.
      Overrides:
      toString in class Object
      Returns:
      an ordered list of the constructors that the makeDataNode will try to use.
    • getSpecialBuilders

      public static List getSpecialBuilders()
      Returns a list of builders which, for a default DataNodeFactory, are invoked before any of the constructor-based ones. These allow cleverer decisions to be made about what kind of node is generated from what object: if a given object could make either a FooDataNode or a BarDataNode but would be better off as a BarDataNode, this can be done even if FooDataNode was higher in the class preference list for this factory. For the default configuration, this list should come first in the list of builders, if the user reconfigures the preferred class list it may slip lower down or disappear from the hierarchy.

      This method is called in the constructor to initialise the factory's default state.

      Returns:
      a list of DataNodeBuilder objects
    • getDefaultClassList

      public static List getDefaultClassList()
      Returns the default class list from which the list of constructor-based builders is initialised.

      This method is called in the constructor to initialise the factory's default state.

      Returns:
      a list of Class objects representing concrete implementations of the DataNode interface