/**
* Copyright 2016-2017 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.roboconf.core.autonomic;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.roboconf.core.ErrorCode;
import net.roboconf.core.model.ParsingError;
import net.roboconf.core.utils.Utils;
/**
* @author Vincent Zurczak - Linagora
*/
public class RuleParser {
private static final Pattern RULE_PATTERN = Pattern.compile( "(?is)^\\s*rule\\s+\"([^\"]*)\"\\s+(.*)when\\s+(.+)\\s+then\\s+(.+)\\s+end\\s*$" );
private static final Pattern SLEEP_PERIOD_PATTERN = Pattern.compile( "(?i)\\bsleep period is\\s+(\\d+)s?" );
private static final Pattern TIME_WINDOW_PATTERN = Pattern.compile( "(?i)\\btime window is\\s+(\\d+)s?" );
private static final String SINGLE_COMMENT_PATTERN = "//.*\r?\n";
private static final String SINGLE_SHARP_COMMENT_PATTERN = "#.*\r?\n";
private static final String MULTILINE_COMMENT_PATTERN = "(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)";
private final List<ParsingError> parsingErrors = new ArrayList<> ();
private final Rule rule = new Rule();
/**
* Constructor.
* @param ruleFile
*/
public RuleParser( File ruleFile ) {
String details = "File name: " + ruleFile.getName();
try {
String s = Utils.readFileContent( ruleFile );
s = s.replaceAll( MULTILINE_COMMENT_PATTERN, "" );
s = s.replaceAll( SINGLE_COMMENT_PATTERN, "" );
s = s.replaceAll( SINGLE_SHARP_COMMENT_PATTERN, "" );
s = s.trim();
Matcher m = RULE_PATTERN.matcher( s );
if( ! m.matches()) {
this.parsingErrors.add( new ParsingError( ErrorCode.RULE_INVALID_SYNTAX, ruleFile, -1 ));
} else {
// Build the rule
String ruleName = m.group( 1 ).trim();
this.rule.setRuleName( ruleName );
String eventName = m.group( 3 ).trim();
this.rule.setEventName( eventName );
String commandNames = m.group( 4 );
for( String commandName : Utils.splitNicelyWithPattern( commandNames, ";|\r?\n" )) {
if( ! Utils.isEmptyOrWhitespaces( commandName ))
this.rule.getCommandsToInvoke().add( commandName );
}
String properties = m.group( 2 );
if(( m = TIME_WINDOW_PATTERN.matcher( properties )).find())
this.rule.setTimingWindow( Integer.parseInt( m.group( 1 )));
if(( m = SLEEP_PERIOD_PATTERN.matcher( properties )).find())
this.rule.setDelayBetweenSucceedingInvocations( Integer.parseInt( m.group( 1 )));
// Validate the rule
if( Utils.isEmptyOrWhitespaces( ruleName ))
this.parsingErrors.add( new ParsingError( ErrorCode.RULE_EMPTY_NAME, ruleFile, -1, details ));
if( Utils.isEmptyOrWhitespaces( eventName ))
this.parsingErrors.add( new ParsingError( ErrorCode.RULE_EMPTY_WHEN, ruleFile, -1, details ));
if( this.rule.getCommandsToInvoke().isEmpty())
this.parsingErrors.add( new ParsingError( ErrorCode.RULE_EMPTY_THEN, ruleFile, -1, details ));
}
} catch( IOException e ) {
this.parsingErrors.add( new ParsingError( ErrorCode.RULE_IO_ERROR, ruleFile, -1, details ));
}
}
/**
* @return the parsingErrors
*/
public List<ParsingError> getParsingErrors() {
return this.parsingErrors;
}
/**
* @return the parsed rule
*/
public Rule getRule() {
return this.rule;
}
}