View Javadoc

1   /* This file is part of COPAL (COntext Provisioning for All).
2    *
3    * COPAL is a part of SM4All (Smart hoMes for All) project.
4    *
5    * COPAL is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU Lesser General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * COPAL is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with COPAL. If not, see <http://www.gnu.org/licenses/>.
17   */
18  package at.ac.tuwien.infosys.sm4all.copal.esper;
19  
20  import java.text.MessageFormat;
21  import org.apache.log4j.Logger;
22  import org.w3c.dom.Node;
23  import at.ac.tuwien.infosys.sm4all.copal.api.ActionQuery;
24  import at.ac.tuwien.infosys.sm4all.copal.api.ContextQuery;
25  import at.ac.tuwien.infosys.sm4all.copal.api.ProcessedEventQuery;
26  import at.ac.tuwien.infosys.sm4all.copal.api.QueryDestroyedException;
27  import at.ac.tuwien.infosys.sm4all.copal.api.event.xml.ActionsFinished;
28  import com.espertech.esper.client.EPAdministrator;
29  import com.espertech.esper.client.EPStatement;
30  
31  /**
32   * Esper subscriber which helps transform Esper event to context events
33   * understood by {@link ContextQuery}. This class is bridge between Esper and
34   * COPAL.
35   * 
36   * @author fei
37   * @author sanjin
38   */
39  public class EventNotifier {
40  
41      private static final String ACTIONS_FINISHED_CRITERIA = MessageFormat.format(
42              "`{0}`", ActionsFinished.INSTANCE.getQualifiedName());
43      private static final Logger LOGGER = Logger.getLogger(EventNotifier.class);
44  
45      private final EPAdministrator administrator;
46      private final ContextQuery query;
47      private final EPStatement statement;
48  
49      /**
50       * Creates Esper subscriber using specified administrator to create Esper
51       * statement from specified context query.
52       * 
53       * @param administrator the Esper administrator.
54       * @param query the context query.
55       */
56      public EventNotifier(final EPAdministrator administrator,
57              final ContextQuery query) {
58          super();
59  
60          this.administrator = administrator;
61          this.query = query;
62          this.statement = createStatement();
63          this.statement.setSubscriber(this);
64      }
65  
66      /**
67       * Called when Esper has new event that is represented with specified XML
68       * node. This method in return calls the context-query for which this
69       * notifier was created.
70       * 
71       * @param node the event.
72       */
73      public void update(final Node node) {
74          try {
75              this.query.onEvent(node.getOwnerDocument());
76          } catch (final QueryDestroyedException ex) {
77              LOGGER.error(
78                      "Query is unexpectedly destroyed! Destroying query's notifier.",
79                      ex);
80              destroy();
81          }
82      }
83  
84      /**
85       * Destroys the Esper statement used to get the update notifications.
86       */
87      public void destroy() {
88          if (LOGGER.isDebugEnabled())
89              LOGGER.debug(MessageFormat.format(
90                      "Destroying ''{0}'' esper statement.",
91                      this.statement.getName()));
92  
93          this.statement.destroy();
94  
95          if (LOGGER.isInfoEnabled())
96              LOGGER.info(MessageFormat.format(
97                      "''{0}'' esper statement destroyed!",
98                      this.statement.getName()));
99      }
100 
101     private EPStatement createStatement() {
102         final String name = this.query.getName();
103 
104         final String expression;
105         if (this.query instanceof ActionQuery)
106             expression = getExpression((ActionQuery) this.query);
107         else if (this.query instanceof ProcessedEventQuery)
108             expression = getExpression((ProcessedEventQuery) this.query);
109         else
110             expression = getExpression(this.query);
111         final EPStatement result = this.administrator.createEPL(expression,
112                 name);
113 
114         if (LOGGER.isDebugEnabled())
115             LOGGER.debug(MessageFormat.format(
116                     "Esper statement created! name={0} expression={1}", name,
117                     expression));
118 
119         return result;
120     }
121 
122     private static String getExpression(final ActionQuery query) {
123         return MessageFormat.format("select * from {0}({1})",
124                 query.getEventType(), query.getCriteria());
125     }
126 
127     private static String getExpression(final ProcessedEventQuery query) {
128         final String result;
129 
130         if (query.hasCriteria())
131             result = MessageFormat.format("select * from {0}({1}) where {2}",
132                     query.getEventType(), ACTIONS_FINISHED_CRITERIA,
133                     query.getCriteria());
134         else
135             result = MessageFormat.format("select * from {0}({1})",
136                     query.getEventType(), ACTIONS_FINISHED_CRITERIA);
137 
138         return result;
139     }
140 
141     private static String getExpression(final ContextQuery query) {
142         String result;
143 
144         if (query.hasCriteria())
145             result = MessageFormat.format("select * from {0}({1})",
146                     query.getEventType(), query.getCriteria());
147         else
148             result = MessageFormat.format("select * from {0}",
149                     query.getEventType());
150 
151         return result;
152     }
153 }