/**
* Copyright 2015-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.commands;
import java.util.ArrayList;
import java.util.Collections;
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.model.beans.AbstractApplication;
/**
* @author Vincent Zurczak - Linagora
*/
public abstract class AbstractCommandInstruction {
private static final Pattern VAR_PATTERN = Pattern.compile( "(\\$\\([^)]*\\))" );
protected final String instruction;
protected final Context context;
protected final int line;
protected boolean syntaxicallyCorrect = false;
/**
* Constructor.
* @param context the context
* @param instruction the instruction
* @param line the line number
*/
public AbstractCommandInstruction( Context context, String instruction, int line ) {
this.instruction = instruction;
this.context = context;
this.line = line;
}
/**
* @return a non-null list of errors, possibly empty
*/
public final List<ParsingError> validate() {
List<ParsingError> errors = new ArrayList<> ();
if( ! this.syntaxicallyCorrect )
errors.add( error( ErrorCode.CMD_INVALID_SYNTAX, "Instruction: " + this.instruction ));
Matcher m = VAR_PATTERN.matcher( this.instruction );
while( m.find()) {
boolean found = false;
String varName = m.group( 1 );
for( String variablePattern : getVariablesToIgnore()) {
if( varName.matches( variablePattern )) {
found = true;
break;
}
}
if( ! found )
errors.add( error( ErrorCode.CMD_UNRESOLVED_VARIABLE, "Variable: " + varName ));
}
if( errors.isEmpty())
errors.addAll( doValidate());
return errors;
}
/**
* @return the (abstract) application this instruction is associated with
*/
public AbstractApplication getApplication() {
return this.context.getApp();
}
/**
* Validates specific items related to sub-classes.
* @return a non-null list of errors
*/
protected abstract List<ParsingError> doValidate();
/**
* @return a non-null list of patterns describing variables to ignore
*/
protected List<String> getVariablesToIgnore() {
return Collections.emptyList();
}
/**
* Updates the context (to be invoked after {@link #validate()}).
*/
public void updateContext() {
// nothing
}
/**
* A shortcut method to create a parsing error with relevant information.
* @param errorCode an error code
* @param details (can be null)
* @return a new parsing error
*/
protected ParsingError error( ErrorCode errorCode, String details ) {
return new ParsingError( errorCode, this.context.getCommandFile(), this.line, details );
}
/**
* A shortcut method to create a parsing error with relevant information.
* @param errorCode an error code
* @return a new parsing error
*/
protected ParsingError error( ErrorCode errorCode ) {
return error( errorCode, null );
}
}