... write an Abstractor

What is an Abstractor

An Abstractor generates and returns an AbstractModel. The model is calculated with a TopicMapObject as its base and with respect to an actual AbstractionContext.

How to access an Abstractor

Any Abstractor must implement the Interface org.tm4j.panckoucke.abstraction.Abstractor. Currently this interface defines two methods.

public AModel generateModel(TopicMapObject tmo, AbstractionContext ac)
  throws UnsupportedOperationException;

Returns an AbstractModel. The Model is a representation of the given TopicMapObject in the provided context, viewed through the eyes of this Abstractor.

public boolean supportsAbstraction(TopicMapObject tmo, AbstractionContext ac);

Allows an application to determine if a given Abstractor is able to serve a specific request. If this method returns false, a subsequent call to generateModel with exactly the same parameters should throw an UnsupportedOperationException.

Note

When using an Abstractor with Panckoucke 0.3.0, the method supportsAbstraction is never called by the panckoucke-library. Instead the ModelProvider calls generateModel directly and passes a thrown UnsupportedOperationException back to the caller.

Three steps

If you want to implement an Abstractor on your own, you will essentially perform three steps, in order to calculate a model

  • Check, if the current request can be processed
  • Obtain a new AbstractModel-instance from a AModelFactory
  • Add nodes to the model and connect them via arcs

Example

Checking if the actual request can be served, is implemented in the supportsAbstraction()-Method. Assuming your abstractor is able to generate models for any given association, your supportsAbstraction-method may look like this

public Class myAssocAbstractor{
  
  [...]
  
  public boolean supportsAbstraction(TopicMapObject tmo, AbstractionContext ac) {
    
    if (tmo == null) return false;
    
    return tmo instanceof Association;

  }
  
  [...]

}
	  

Implementations of the generateModel-method should check, if supportsAbstraction(...) returns true and if so, create a model.

You create a new empty instance of a model by a call to the createAModel-method of a org.tm4j.panckoucke.model.AModelFactory. Once you retrieved the model you add arcs and nodes to the model via the appropriate calls.

public Class myAssocAbstractor{


  [...]
  
  public AModel generateModel(TopicMapObject tmo, AbstractionContext ac) {
  
    // check
    if (!supportsAbstraction(tmo, ac)) throw new UnsupportedOperationException();
    
    // create a Model
    AModel model = modelFactory.createAModel();
    
    try {
      Association assoc = (Association) tmo;
      
      // add a node. The first node added is per default used as the centernode of that model 
      AMNode root_node = model.createNode(NameUtil.labelFor(assoc), assoc, AMGestaltRegistry.GESTALT_ASSOCIATION);
      
      
      // add the relationship to the containing topicmap
      TopicMap tm = assoc.getTopicMap();
      
      AMNode tmNode  = model.createNode(NameUtil.labelFor(tm), tm, AMGestaltRegistry.GESTALT_TOPICMAP);
      AMArc arc = model.createArc(tmNode, "toTopicmap");
      model.addEndNode(arc, root_node);
    
    
    [...]
  
  }
	  

The ModelFactory

If you plan to manage a ModelFactory by your own, you may instantiate panckoucke's default implementation org.tm4j.panckoucke.impl.model.AModelFactoryImp.

However, if you plan to use your Abstractor with Panckoucke-Api (with the ModelProvider), you will be supplied with a ModelFactory.

When creating your model, you should be eager to pass only those AMMember-Objects( AMMember is the superclass of Nodes and Arcs) to a AModel, that you did receive from exactly this instance. Sharing AMMembers between different model-instances is not supported and will most likely lead to a UnknownMemberIDException.

The Gestalten

The Gestalt-System was introduced to enable the abstraction layer to pass some kind of metainformation along with the members. This metainformation is intended to describe the nature of the model members, not their actual apperance. Any particular Renderer may render a Node of gestalt PLAYER in its own distinct manner.

Any Abstractor who feels the need to define less generic Gestalt-Types is free to do so. The Abstractor may register the new gestalten with the GestaltRegistry. A collaborating Renderer is then able to compare the Gestalt of ModelMembers to the specialized Types. In order to provide a common hook for a custom gestalt the Abstractor may define it as a public static field.

The ModelProvider

To write an Abstractor to be used with Panckoucke ModelProvider you must ensure the folllowing:

Your Abstractor must implement the Interface org.tm4j.panckoucke.abstraction.InstantiableAbstractor. This Interface extends the Abstractor-Interface and defines one additional method:


  public void setModelFacory(AModelFactory factory)

The ModelProvider guarantees that the setModelFactory(....)-method is called before the first call to any of the methods defined in the base interface Abstractor

Your implementation must provide a no-argument-constructor in order to let the ModelProvider instantiate your class dynamically.

Things to keep in mind

Abstractors are supposed to work in multithreaded enviroments. To ensure, that your implementation will function properly when called from concurrent threads, you may consider to implement it stateless (no instance variables).