View Javadoc
1   /*
2    * Copyright (c) 2002-2018, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.easyrulesbot.service.bot;
35  
36  import fr.paris.lutece.plugins.chatbot.business.BotPost;
37  import fr.paris.lutece.plugins.easyrulesbot.service.bot.rules.BotRule;
38  import fr.paris.lutece.plugins.easyrulesbot.service.response.filters.ResponseFilter;
39  import fr.paris.lutece.plugins.easyrulesbot.service.response.exceptions.ResponseProcessingException;
40  import fr.paris.lutece.portal.service.security.LuteceUser;
41  import fr.paris.lutece.portal.service.security.SecurityService;
42  import fr.paris.lutece.portal.service.util.AppLogService;
43  
44  import org.easyrules.api.Rule;
45  import org.easyrules.api.RulesEngine;
46  
47  import java.io.Serializable;
48  
49  import java.util.ArrayList;
50  import java.util.List;
51  import java.util.Locale;
52  import java.util.Map;
53  import java.util.concurrent.ConcurrentHashMap;
54  
55  import javax.servlet.http.HttpServletRequest;
56  
57  /**
58   * BotExecutor
59   */
60  public class BotExecutor implements Serializable
61  {
62      public static final String DATA_USER_FIRSTNAME = "user_firstname";
63      public static final String DATA_USER_LASTNAME = "user_lastname";
64      public static final String DATA_USER_EMAIL = "user_email";
65      private static final long serialVersionUID = 1L;
66      private EasyRulesBot _bot;
67      private Locale _locale;
68      private BotRule _currentRule;
69      private Map<String, String> _mapData = new ConcurrentHashMap<String, String>( );
70  
71      /**
72       * Constructor
73       * 
74       * @param bot
75       *            The bot to execute
76       * @param locale
77       *            The locale
78       */
79      public BotExecutor( EasyRulesBot bot, Locale locale )
80      {
81          _bot = bot;
82          _locale = locale;
83      }
84  
85      /**
86       * Returns the Locale
87       * 
88       * @return The Locale
89       */
90      public Locale getLocale( )
91      {
92          return _locale;
93      }
94  
95      /**
96       * Gets the question
97       * 
98       * @return The question
99       */
100     public String getQuestion( )
101     {
102         String strQuestion = null;
103 
104         if ( _currentRule != null )
105         {
106             strQuestion = _currentRule.getMessage( _mapData, _locale );
107         }
108 
109         return strQuestion;
110     }
111 
112     /**
113      * Process the response
114      * 
115      * @param strUserMessage
116      *            The user message
117      * @return The list of post
118      * @throws ResponseProcessingException
119      *             if an exception occurs during processing
120      */
121     public List<BotPost> processResponse( String strUserMessage ) throws ResponseProcessingException
122     {
123         List<BotPost> listBotPost = new ArrayList<>( );
124         
125         String strResponseValue = processFilters( strUserMessage );
126 
127         if ( _currentRule != null )
128         {
129             strResponseValue = _currentRule.getResponseProcessor( ).processResponse( strResponseValue, _locale, _mapData );
130             _mapData.put( _currentRule.getDataKey( ), strResponseValue );
131 
132             String strResponseComment = _currentRule.getResponseComment( _mapData, _locale );
133 
134             if ( ( strResponseComment != null ) && !strResponseComment.trim( ).equals( "" ) )
135             {
136                 BotPost post = new BotPost( strResponseComment, BotPost.CONTENT_TYPE_TEXT );
137                 listBotPost.add( post );
138             }
139         }
140         return listBotPost;
141     }
142 
143     /**
144      * Process filters
145      * 
146      * @param strResponse
147      *            The response
148      * @return The filterd response
149      * @throws ResponseProcessingException
150      *             if an exception occurs during processing
151      */
152     private String processFilters( String strResponse ) throws ResponseProcessingException
153     {
154         String strResponseValue = strResponse;
155 
156         for ( ResponseFilter filter : _bot.getResponseFilters( ) )
157         {
158             strResponseValue = filter.filterResponse( strResponseValue, _locale, _mapData );
159         }
160 
161         return strResponseValue;
162     }
163 
164     /**
165      * Sets the current rule
166      * 
167      * @param rule
168      *            The rule
169      */
170     public void setCurrentRule( BotRule rule )
171     {
172         _currentRule = rule;
173     }
174 
175     /**
176      * Executes rules. NB : Should be thread safe.
177      */
178     public synchronized void fireRules( )
179     {
180         _currentRule = null;
181 
182         RulesEngine engine = _bot.getRulesEngine( );
183 
184         for ( Rule rule : engine.getRules( ) )
185         {
186             if ( rule instanceof BotRule )
187             {
188                 ( (BotRule) rule ).setExecutor( this );
189             }
190         }
191 
192         engine.fireRules( );
193     }
194 
195     /**
196      * Trace utils
197      */
198     public void traceData( )
199     {
200         for ( String strKey : _mapData.keySet( ) )
201         {
202             AppLogService.info( strKey + " : " + _mapData.get( strKey ) );
203         }
204     }
205 
206     /**
207      * Gets all the data map
208      * 
209      * @return The data map
210      */
211     public Map<String, String> getDataMap( )
212     {
213         return _mapData;
214     }
215 
216     /**
217      * Returns the bot name
218      * 
219      * @return the bot name
220      */
221     public String getBotName( )
222     {
223         return _bot.getName( _locale );
224     }
225 
226     /**
227      * Add MyLutece user's info to data map
228      * 
229      * @param request
230      */
231     public void setLuteceUser( HttpServletRequest request )
232     {
233         if ( SecurityService.isAuthenticationEnable( ) )
234         {
235             LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );
236 
237             if ( user != null )
238             {
239                 _mapData.put( DATA_USER_FIRSTNAME, user.getUserInfo( LuteceUser.NAME_GIVEN ) );
240                 _mapData.put( DATA_USER_LASTNAME, user.getUserInfo( LuteceUser.NAME_FAMILY ) );
241                 _mapData.put( DATA_USER_EMAIL, user.getEmail( ) );
242             }
243         }
244     }
245 
246     /**
247      * Returns bot avatar URL
248      * 
249      * @return The avatar URL
250      */
251     public Object getBotAvatarUrl( )
252     {
253         return _bot.getAvatarUrl( );
254     }
255 
256     
257 }