1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package fr.paris.lutece.plugins.easyrulesbot.service.yaml;
36
37 import fr.paris.lutece.plugins.easyrulesbot.service.yaml.model.YamlFilter;
38 import fr.paris.lutece.plugins.easyrulesbot.service.yaml.model.YamlBot;
39 import fr.paris.lutece.plugins.easyrulesbot.service.yaml.model.YamlRule;
40 import fr.paris.lutece.plugins.easyrulesbot.service.yaml.model.YamlCondition;
41 import com.fasterxml.jackson.databind.ObjectMapper;
42 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
43 import fr.paris.lutece.plugins.chatbot.service.BotService;
44 import fr.paris.lutece.plugins.easyrulesbot.service.bot.rules.BotRule;
45 import fr.paris.lutece.plugins.easyrulesbot.service.bot.rules.conditions.Condition;
46 import fr.paris.lutece.plugins.easyrulesbot.service.bot.rules.conditions.ConditionsService;
47 import fr.paris.lutece.plugins.easyrulesbot.service.bot.EasyRulesBot;
48 import fr.paris.lutece.plugins.easyrulesbot.service.response.filters.FiltersService;
49 import fr.paris.lutece.plugins.easyrulesbot.service.response.filters.ResponseFilter;
50 import fr.paris.lutece.plugins.easyrulesbot.service.response.processors.ProcessorsService;
51 import fr.paris.lutece.plugins.easyrulesbot.service.response.processors.ResponseProcessor;
52 import fr.paris.lutece.portal.service.util.AppLogService;
53 import fr.paris.lutece.portal.service.util.AppPathService;
54 import java.io.File;
55 import java.io.FilenameFilter;
56 import java.io.IOException;
57 import java.util.ArrayList;
58 import java.util.List;
59 import org.apache.commons.io.FileUtils;
60 import org.easyrules.api.RulesEngine;
61 import org.easyrules.spring.RulesEngineFactoryBean;
62
63
64
65
66 public class YamlBotLoader
67 {
68 private static final String PATH_BOTS = "/WEB-INF/plugins/easyrulesbot/bots";
69 private static RulesEngineFactoryBean _factory;
70
71 public static void loadBots( )
72 {
73 String strBotPath = AppPathService.getAbsolutePathFromRelativePath( PATH_BOTS );
74 File fBotPath = new File( strBotPath );
75
76 File [ ] files = fBotPath.listFiles( new YamlFilenameFilter( ) );
77 AppLogService.debug( "Loading YAML bots ... " );
78 for ( File file : files )
79 {
80 try
81 {
82 String strYaml = FileUtils.readFileToString( file, "UTF-8" );
83 YamlBot yBot = loadYamlBot( strYaml );
84 EasyRulesBot bot = createBot( yBot );
85 BotService.register( bot );
86 AppLogService.debug( "New YAML bot registered : " + yBot.getName( ) );
87 }
88 catch( IOException | YamlBotLoadingException ex )
89 {
90 AppLogService.error( "Unable to load bot. Error : " + ex.getMessage( ), ex );
91 }
92 }
93 }
94
95 public static YamlBot loadYamlBot( String strYaml ) throws IOException
96 {
97 ObjectMapper mapper = new ObjectMapper( new YAMLFactory( ) );
98
99 YamlBot bot = mapper.readValue( strYaml, YamlBot.class );
100
101 AppLogService.debug( "Loaded bot : " + bot );
102 return bot;
103 }
104
105
106
107
108
109
110
111
112
113
114 public static EasyRulesBot createBot( YamlBot yamlBot ) throws YamlBotLoadingException
115 {
116 EasyRulesBot bot = new EasyRulesBot( );
117 bot.setKey( yamlBot.getKey( ) );
118 bot.setName( yamlBot.getName( ) );
119 bot.setDescription( yamlBot.getDescription( ) );
120 bot.setWelcomeMessage( yamlBot.getWelcomeMessage( ) );
121 bot.setAvatarUrl( yamlBot.getAvatarUrl( ) );
122 bot.setStandalone( yamlBot.getStandalone( ) );
123 List<String> listLanguages = new ArrayList<String>();
124 listLanguages.add( yamlBot.getLanguage() );
125 bot.setListAvailableLanguages( listLanguages );
126
127
128 RulesEngine engine = getEngine( );
129 for ( YamlRule yamlRule : yamlBot.getRules( ) )
130 {
131 BotRule rule = new BotRule( );
132 rule.setName( yamlRule.getRule( ) );
133 rule.setDescription( yamlRule.getDescription( ) );
134 rule.setPriority( yamlRule.getPriority( ) );
135 rule.setMessageTemplate( yamlRule.getMessage( ) );
136 rule.setDataKey( yamlRule.getDataKey( ) );
137 ResponseProcessor processor = ProcessorsService.getProcessor( yamlRule.getProcessor( ) );
138 if ( processor == null )
139 {
140 throw new YamlBotLoadingException( "Failed to create bot : unable to find processor " + yamlRule.getProcessor( ) );
141 }
142 rule.setResponseProcessor( processor );
143 rule.setResponseCommentTemplate( yamlRule.getResponseComment( ) );
144 List<Condition> listConditions = new ArrayList<>( );
145 if( yamlRule.getConditions( ) != null )
146 {
147 for ( YamlCondition yamlCondition : yamlRule.getConditions( ) )
148 {
149 Condition condition = ConditionsService.getCondition( yamlCondition.getCondition( ) );
150 if ( condition == null )
151 {
152 throw new YamlBotLoadingException( "Failed to create bot : unable to find condition " + yamlCondition.getCondition( ) );
153 }
154 condition.setParameters( yamlCondition.getParameters() );
155 listConditions.add( condition );
156 }
157 }
158 rule.setListConditions( listConditions );
159 rule.setButtons( yamlRule.getButtons() );
160 engine.registerRule( rule );
161 }
162 bot.setRulesEngine( engine );
163
164 List<ResponseFilter> listFilters = new ArrayList<>( );
165 for ( YamlFilter yamlFilter : yamlBot.getFilters( ) )
166 {
167 ResponseFilter filter = FiltersService.getFilter( yamlFilter.getFilter( ) );
168 if ( filter == null )
169 {
170 throw new YamlBotLoadingException( "Failed to create bot : unable to find filter " + yamlFilter.getFilter( ) );
171 }
172 listFilters.add( filter );
173 }
174 bot.setListResponseFilters( listFilters );
175
176 AppLogService.debug( "Loaded bot : " + bot );
177
178 return bot;
179 }
180
181 private static RulesEngine getEngine( )
182 {
183 if ( _factory == null )
184 {
185 _factory = new RulesEngineFactoryBean( );
186 _factory.setSkipOnFirstAppliedRule( true );
187 _factory.setSkipOnFirstFailedRule( true );
188 _factory.setPriorityThreshold( 100 );
189 _factory.setSilentMode( false );
190 }
191 return _factory.getObject( );
192 }
193
194 private static class YamlFilenameFilter implements FilenameFilter
195 {
196 @Override
197 public boolean accept( File dir, String filename )
198 {
199 return filename.endsWith( ".yml" ) || filename.endsWith( ".yaml" );
200 }
201 }
202 }