This page (revision-25) was last changed on 18-Dec-2012 01:33 by Albrecht Striffler

This page was created on 17-Dec-2012 14:28 by Daniel Zügner

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Page revision history

Version Date Modified Size Author Changes ... Change note
25 18-Dec-2012 01:33 12 KB Albrecht Striffler to previous
24 18-Dec-2012 01:33 12 KB Albrecht Striffler to previous | to last
23 18-Dec-2012 01:32 12 KB Albrecht Striffler to previous | to last
22 18-Dec-2012 01:32 12 KB Albrecht Striffler to previous | to last
21 17-Dec-2012 21:34 12 KB Sebastian Furth to previous | to last

Page References

Incoming links Outgoing links

Version management

Difference between version and

At line 1 changed 3 lines
%%(color:red)
__DEPRECATED__
%%
%%(color:red) DEPRECATED
At line 5 removed one line
[{TableOfContents }]
At line 5 added one line
[{TableOfContents }]
At line 14 changed one line
SubtreeHandler has only one abstract method. The non-abstract methods are described further down.
SubtreeHandler has only one abstract methods. The non-abstract methods are described further down.
At line 18 changed one line
public abstract Collection<Message> create(KnowWEArticle article, Section s);
public abstract Collection<KDOMReportMessage> create(KnowWEArticle article, Section s);
At line 23 changed 2 lines
The Section is a section of the type the handler is registered for, the KnowWEArticle is the article that called this method with this specific Section.
The returned Collection of Messages needs to contain the Messages produced by the SubTreeHandler (read more about it in the chapter about Messages further below).
The Section is a section of the type the handler is registered for, the KnowWEArticle is the article that called this method with this specific Section. Note that this article can be another article than the article that is returned by calling the getArticle()-method of the Section, becaus Sections can also be included. If, for example, a Section from article A is included by article B and article B is currently revising the KDOM and executes this handler with this section, the attribute KnowWEArticle given in this method will point to article B, while the getArticle()-method of the Section still points to article A.\\
The returned Collection of KDOMReportMessages needs to contain the Messages produced by the SubTreeHandler (read more about it in the chapter about Messages further below).
At line 27 changed one line
If you have created your own SubtreeHandler and want to register the handler to a type, call the addSubtreeHandler-method (inherited from AbstractType) of the type object you want to attach the handler to:
If you have created your own SubtreeHandler and want to register the handler to a type, call the addSubtreeHandler-method (inherited from AbstractKnowWEObjectType) of the type object you want to attach the handler to:
At line 38 changed 2 lines
After the KDOM of an article is completed, for all Sections whos Type has SubtreeHandlers registered to it, the method create(...) will be executed for all these SubtreeHandlers. The order of execution of the handlers is very specific and it works like this: At first, a list of all Sections of the KDOM is retrieved from the article in post-order. So the children of a Section are ordered prior to the Section itself. Children of the same Section appear in this list in the same order as they appear in the text of the article.\\
After having this list of Sections, another map is created. The map contains lists with Sections whos Type have SubtreeHandlers with a certain priority registered to them. These lists are hashed after this priority and the map is sorted in a descending order (of priorities). Inside the single lists with all Sections with handlers of a certain priority, the Sections appear in the same order as they appear in the original list with all Sections in post-order. Sections can appear multiple times or not at all in this map: If their Type has multiple SubtreeHandlers with different priorities, the same Section will appear in every list of each different priority of its handlers. If the Type has no SubtreeHandler, it simply will no appear in any list in the map.\\
After the KDOM of an article is completed, for all Sections whos KnowWEObjectType has SubtreeHandlers registered to it, the method create(...) will be executed for all these SubtreeHandlers. The order of execution of the handlers is very specific and it works like this: At first, a list of all Sections of the KDOM is retrieved from the article in post-order. So the children of a Section are ordered prior to the Section itself. Children of the same Section appear in this list in the same order as they appear in the text of the article.\\
After having this list of Sections, another map is created. The map contains lists with Sections whos KnowWEObjectType have SubtreeHandlers with a certain priority registered to them. These lists are hashed after this priority and the map is sorted in a descending order (of priorities). Inside the single lists with all Sections with handlers of a certain priority, the Sections appear in the same order as they appear in the original list with all Sections in post-order. Sections can appear multiple times or not at all in this map: If their KnowWEObjectType has multiple SubtreeHandlers with different priorities, the same Section will appear in every list of each different priority of its handlers. If the KnowWEObjectType has no SubtreeHandler, it simply will no appear in any list in the map.\\
At line 42 changed one line
Given is the following simplified KDOM. Each node represents a Section with a certain Type denoted underlined in the top. The SubtreeHandlers registered to the Types are denoted below, together with the Priority they were registered with.
Given is the following simplified KDOM. Each node represents a Section with a certain KnowWEObjectType denoted underlined in the top. The SubtreeHandlers registered to the KnowWEObjectTypes are denoted below, together with the Priority they were registered with.
At line 46 changed one line
QuestionsSection, XCList, XCList, Include, RulesSection, SolutionsSection, Article
QuestionsSection, XCList, XCList, Include, RulesSection, SolutionsSection, KnowWEArticle
At line 53 changed one line
}}}This map now pretty much represents the order the SubtreeHandlers are executed in. KnowWE will simply iterate in descending priority-order over the lists of the map and executes all SubtreeHandlers of the priority of the list that is currently iterated. If the Type of the Section also contains handlers with a different priority, these handlers will not be executed until the list with the corresponding priority is iterated.
}}}
This map now pretty much represents the order the SubtreeHandlers are executed in. KnowWE will simply iterate in descending priority-order over the lists of the map and executes all SubtreeHandlers of the priority of the list that is currently iterated. If the KnowWEObjectType of the Section also contains handlers with a different priority, these handlers will not be executed until the list with the corresponding priority is iterated.
At line 57 added 3 lines
If you use messages in a SubtreeHandler, consider that the method create(...) of the SubtreeHandlers can be executed multiple times for the same Section object (because of the incremental update). Therefore, the Collection of messages stored by the SubtreeHandler needs to always represent the current state of this Handler, including the case that no messages are produced at all. In this case, return or store an empty Collection (to overwrite possible error messages created in a previous execution of the handler with the same Section object).
If you want the messages to be preserved, for example in case the execution of the handler gets aborted due to the incremental update, return null like before.\\
At line 58 changed 2 lines
Basically, returning a Collection of messages in the handler equals the storage of a Collection of messages using the storeMessages() methods provided by KnowWEUtils. Using Messages and returning them instead of storing other types makes it just easier, because you have to care less about correct usage and the correct attributes required by the methods from KnowWEUtils. It's also shorter code ;-) .
Of course all of this only applies if you actually use messages in your handler. If you don't, you can just return null everywhere. Simple rule: As soon as you return or store messages at one of the possible outcomes (returns) of the create method, you have to do it on every.
__Hint:__ Use Arrays.asList((KDOMReportMessage) yourMessage) to create a Collection if you just have a single message.
At line 62 changed one line
__Hint:__ Use Arrays.asList((KDOMReportMessage) yourMessage) to create a Collection if you just have a single message.
Different types of messages can be used in SubtreeHandlers. However the recommented type is the KDOMReportMessage, since it is supported in the type of the Collection returned by the create method. Basically, returning a Collection of messages in the handler equals the storage of a Collection of messages using the storeMessages() methods provided by KnowWEUtils. Using KDOMReportMessages and returning them instead of storing other types makes it just easier, because you have to care less about correct usage and the correct attributes required by the methods from KnowWEUtils. It's also shorter code ;-) .
Of course all of this only applies if you actually use messages in your handler. If you don't, you can just return null everywhere. Simple rule: As soon as you return or store messages at one of the possible outcomes (returns) of the create method, you have to do it on every.
At line 68 added one line
!KDOMReportMessages in SubtreeHandlers
At line 66 changed 2 lines
!Messages in SubtreeHandlers
To understand how Messages should and should not be used in SubtreeHandlers, take a look at the following examples. Note, that KDOMNotice, KDOMWarning and KDOMError are abstract classes. In the examples they are used only to show the idea of which subclass of the Message should be used in which situation. If you actually implement your handler, you again need subclasses of these three subclasses. A variety of them can by found in de.d3web.we.kdom.report.message in the KnowWE-core project.
To understand how KDOMReportMessages should and should not be used in SubtreeHandlers, take a look at the following examples. Note, that KDOMNotice, KDOMWarning and KDOMError are abstract classes. In the examples they are used only to show the idea of which subclass of the KDOMReportMessage should be used in which situation. If you actually implement your handler, you again need subclasses of these three subclasses. A variety of them can by found in de.d3web.we.kdom.report.message in the KnowWE-core project.
At line 74 changed one line
public Collection<Message> create(Article article, Section s) {
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section s) {
At line 78 changed one line
return Arrays.asList((Message) new KDOMNotice("Object created");
return Arrays.asList((KDOMReportMessage) new KDOMNotice("Object created");
At line 80 changed one line
return Arrays.asList((Message) new KDOMError("Object NOT created");
return Arrays.asList((KDOMReportMessage) new KDOMError("Object NOT created");
At line 88 changed one line
public Collection<Message> create(Article article, Section s) {
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section s) {
At line 90 changed one line
List<Message> msgs = new ArrayList<Message>();
List<KDOMReportMessage> msgs = new ArrayList<KDOMReportMessage>();
At line 105 changed one line
public Collection<Message> create(Article article, Section s) {
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section s) {
At line 108 changed one line
return Arrays.asList((Message) new KDOMError("Object NOT created");
return Arrays.asList((KDOMReportMessage) new KDOMError("Object NOT created");
At line 124 changed one line
public Collection<Message> create(Article article, Section s) {
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section s) {
At line 127 changed one line
return Arrays.asList((Message) new KDOMError("Object NOT created");
return Arrays.asList((KDOMReportMessage) new KDOMError("Object NOT created");
At line 131 changed one line
return new ArrayList<Message>(0);
return new ArrayList<KDOMReportMessage>(0);
At line 140 changed one line
public Collection<Message> create(Article article, Section s) {
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section s) {
At line 148 changed one line
return Arrays.asList((Message) new KDOMNotice("Object created");
return Arrays.asList((KDOMReportMessage) new KDOMNotice("Object created");
At line 150 changed one line
return Arrays.asList((Message) new KDOMError("Object NOT created");
return Arrays.asList((KDOMReportMessage) new KDOMError("Object NOT created");
At line 162 added 57 lines
!d3web.report.Messages in SubtreeHandlers
Because the type of the Collection returned by create is KDOMReportMessage, it is highly recommended to use only that type inside the SubtreeHandlers. Use the d3web.report.Message only if they, for example, are returned by a d3web builder. Note that you cannot use that message type in the returned Collection, therefore you have to store them manually with AbstractKnowWEObjectType#storeMessages(KnowWEArticle, Section, Class, Collection<Message>) and return null instead. The methods to store messages in the AbstractKnowWEObjectType are simply using the corresponding methods from KnowWEUtils with the message type already preselected, to make usage a little bit easier. Check out the Javadocs for right use of the remaining attributes and also be aware, that you can use all methods to store Messages only once for each set of attributes (KnowWEArticle, Section, Class of source). If you use the method a second time with the same attributes, the first Collection gets overwritten.
\\
\\
__Examples:__
Right:
%%prettify
{{{
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section s) {
doThis();
doThat();
if (a) {
AbstractKnowWEObjectType.storeSingleMessage(article, s, this.getClass(), new Message("Object created"));
return null;
} else {
AbstractKnowWEObjectType.storeSingleMessage(article, s, this.getClass(), new Message("Object NOT created"));
return null;
}
}
}}}
/%
You can already see, it's less elegant.\\
Note, that the there is a special method for storing just one Message. But be aware, that you also can use this method only once for each KnowWEArticle, Section and Class of the source. So if you want to store more than one message for one outcome of the create method, you have to use Collections.
\\
\\
Wrong:
%%prettify
{{{
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section s) {
doThis();
if (b) {
AbstractKnowWEObjectType.storeSingleMessage(article, s, this.getClass(), new Message("Object NOT created"));
return;
}
doThat();
// everything is ok, so there is no need for a Message?!
return null;
}
}}}
/%
The problem is basically the same as in the wrong example for KDOMReportMessages. At the first return a Message is stored, at the second, nothing is done. So if the handler is executed a second time and b == false while it was true the first time, the old Message doesn't get overwritten.
!Other message types in SubtreeHandlers
Because the type of the Collection returned by create is KDOMReportMessage, it is highly recommended to use only that type inside the SubtreeHandlers. But if you want to use your own type of messages, because somehow the already given types don't match your requirements, you can of course do that. To store them, the same rules apply as for the other message types. However you probably have to directly use the methods of KnowWEUtils to store them:
%%prettify
{{{
public static void storeMessages(KnowWEArticle article, Section<?> sec,
Class<?> source, Class<MSGType> msgType, Collection<MSGType> msgs);
}}}
/%
Parameters:\\
First is the article you are storing the message for. That is not necessarily the same as the one you get calling Section#getArticle(), because Sections can also be included.
Second is the Section you are storing the message for. Third the Class of the source of the message. Fourth you need the class of the message type you want to store, fifth is the Collection of messages of this type.
At line 170 changed one line
public Collection<Message> create(Article article, Section<QuestionDef> sec) {
public Collection<KDOMReportMessage> create(KnowWEArticle article, Section<QuestionDef> sec) {
At line 235 removed 9 lines
%%TODO
Review the SubtreeHandler HowTo in detail!
%
%%Todo
update method signatures (class and method names have changed!?)
%