An Abstractor generates and returns an AbstractModel. The model is calculated with a TopicMapObject as its base and with respect to an actual AbstractionContext.
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.
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.
If you want to implement an Abstractor on your own, you will essentially perform three steps, in order to calculate a model
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); [...] }
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 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.
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.