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.internal;
19  
20  import java.text.MessageFormat;
21  import org.apache.log4j.Logger;
22  import org.w3c.dom.Document;
23  import at.ac.tuwien.infosys.sm4all.copal.api.ActionQuery;
24  import at.ac.tuwien.infosys.sm4all.copal.api.ContextListener;
25  import at.ac.tuwien.infosys.sm4all.copal.api.ContextQuery;
26  import at.ac.tuwien.infosys.sm4all.copal.api.ProcessedEventQuery;
27  import at.ac.tuwien.infosys.sm4all.copal.api.QueryDestroyedException;
28  import at.ac.tuwien.infosys.sm4all.copal.api.event.xml.ActionsFinished;
29  import com.espertech.esper.client.EPAdministrator;
30  import com.espertech.esper.client.EPStatement;
31  import com.espertech.esper.client.EventBean;
32  import com.espertech.esper.client.UpdateListener;
33  
34  /**
35   * Esper's UpdateListener which helps transform Esper's event to context events
36   * understood by {@link ContextListener}.
37   * 
38   * @author fei
39   * @author sanjin
40   */
41  public class EventNotifier implements UpdateListener {
42  
43      private static final String ACTIONS_FINISHED_CRITERIA = MessageFormat.format(
44              "`{0}`", ActionsFinished.INSTANCE.getQualifiedName());
45      private static final Logger LOGGER = Logger.getLogger(EventNotifier.class);
46  
47      private final EPAdministrator administrator;
48      private final ContextQuery query;
49      private final EPStatement statement;
50  
51      /**
52       * Creates Esper's update listener using specified administrator to create
53       * Esper statement from specified context query.
54       * 
55       * @param administrator the Esper administrator.
56       * @param query the context query.
57       */
58      public EventNotifier(final EPAdministrator administrator,
59              final ContextQuery query) {
60          super();
61  
62          this.administrator = administrator;
63          this.query = query;
64          this.statement = createStatement();
65          this.statement.addListener(this);
66      }
67  
68      @Override
69      public void update(final EventBean[] newEvents, final EventBean[] oldEvents) {
70          if ((newEvents == null) || (newEvents.length == 0))
71              return;
72  
73          Object event;
74          for (final EventBean eventBean : newEvents) {
75              event = eventBean.get("*");
76              if (event instanceof Document)
77                  try {
78                      this.query.onEvent((Document) event);
79                  } catch (final QueryDestroyedException ex) {
80                      LOGGER.error(
81                              "Query is unexpectedly destroyed! Destroying query's notifier.",
82                              ex);
83                      destroy();
84                  }
85              else
86                  LOGGER.warn("Recieved non-context event! Ignoring.");
87          }
88      }
89  
90      /**
91       * Destroys the Esper statement used to get the update notifications.
92       */
93      public void destroy() {
94          if (LOGGER.isDebugEnabled())
95              LOGGER.debug(MessageFormat.format(
96                      "Destroying ''{0}'' esper statement.",
97                      this.statement.getName()));
98  
99          this.statement.destroy();
100 
101         if (LOGGER.isInfoEnabled())
102             LOGGER.info(MessageFormat.format(
103                     "''{0}'' esper statement destroyed!",
104                     this.statement.getName()));
105     }
106 
107     private EPStatement createStatement() {
108         final String name = this.query.getName();
109 
110         final String expression;
111         if (this.query instanceof ActionQuery)
112             expression = getExpression((ActionQuery) this.query);
113         else if (this.query instanceof ProcessedEventQuery)
114             expression = getExpression((ProcessedEventQuery) this.query);
115         else
116             expression = getExpression(this.query);
117         final EPStatement result = this.administrator.createEPL(expression,
118                 name);
119 
120         if (LOGGER.isDebugEnabled())
121             LOGGER.debug(MessageFormat.format(
122                     "Esper statement created! name={0} expression={1}", name,
123                     expression));
124 
125         return result;
126     }
127 
128     private static String getExpression(final ActionQuery query) {
129         return MessageFormat.format("select * from {0}({1})",
130                 query.getEventType(), query.getCriteria());
131     }
132 
133     private static String getExpression(final ProcessedEventQuery query) {
134         final String result;
135 
136         if (query.hasCriteria())
137             result = MessageFormat.format("select * from {0}({1}) where {2}",
138                     query.getEventType(), ACTIONS_FINISHED_CRITERIA,
139                     query.getCriteria());
140         else
141             result = MessageFormat.format("select * from {0}({1})",
142                     query.getEventType(), ACTIONS_FINISHED_CRITERIA);
143 
144         return result;
145     }
146 
147     private static String getExpression(final ContextQuery query) {
148         String result;
149 
150         if (query.hasCriteria())
151             result = MessageFormat.format("select * from {0}({1})",
152                     query.getEventType(), query.getCriteria());
153         else
154             result = MessageFormat.format("select * from {0}",
155                     query.getEventType());
156 
157         return result;
158     }
159 }