/*******************************************************************************
* Copyright 2012 I3M-GRyCAP
*
* 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 org.grycap.vmrc.utils.parsing;
import java.util.Hashtable;
import org.apache.log4j.Logger;
import org.grycap.vmrc.entity.Application;
public class VMIStatement {
protected String attribute;
protected String operator;
protected Object value;
private int rankValue;
private String expression;
private Logger log;
private static String[] OPERATORS = {"<",">","<=",">=","="};
private static Hashtable<String,String> htLangMap;
public VMIStatement(String expression) throws UnableToParseException{
this.log = Logger.getLogger(getClass());
this.rankValue = (expression.startsWith("soft") ? new Integer(expression.split(" ")[1]).intValue() : -1);
this.expression = expression;
htLangMap = new Hashtable<String,String>();
populateLangMap(htLangMap);
if (this.expression.contains("disk.applications"))
parseApplication();
else parse();
}
private boolean isValidAttribute(String attrName){
return this.htLangMap.containsKey(attrName);
}
/**
* Mapping between the VMI description language attributes and
* the Hibernate entity names in an HQL query.
*
* Assume vmi as VMI, os as OS, app as Application
* @param ht
*/
private void populateLangMap(Hashtable<String,String> ht){
ht.put("system.name", "vmi.name");
ht.put("system.hypervisor", "vmi.hypervisor");
ht.put("system.location", "vmi.location");
ht.put("cpu.arch", "vmi.arch");
ht.put("cpu.count", "os.name");
ht.put("disk.size", "vmi.diskSize");
ht.put("disk.os.name", "os.name");
ht.put("disk.os.name", "os.name");
ht.put("disk.os.flavour", "os.flavour");
ht.put("disk.os.version", "os.version");
ht.put("disk.os.credentials.user", "vmi.userLogin");
ht.put("disk.os.credentials.password", "vmi.userPassword");
ht.put("disk.applications", "vmi.applications");
}
public boolean isSoft(){return rankValue != -1;}
public String getAttribute(){return attribute;}
public String getOperator(){return operator;}
public Object getValue(){return value;}
public void setValue(Object value){
this.value = value;
}
/**
* @return the rankValue
*/
public int getRankValue() {
return rankValue;
}
/**
* @param rankValue the rankValue to set
*/
public void setRankValue(int rankValue) {
this.rankValue = rankValue;
}
private void parseApplication() throws UnableToParseException{
try{
String appName = "", appVersion = "", appPath = "";
this.attribute = "disk.applications";
int offset = 0;
if (expression.startsWith("soft")) offset = 2;
String[] tokens = expression.split(" ");
appName = filter(tokens[offset + 4]);
if (tokens.length >= offset + 7){
this.operator = tokens[offset + 6];
appVersion = filter(tokens[offset + 7]);
}
if (tokens.length >= offset + 10){
appPath = filter(tokens[offset + 10]);
}
this.value = new Application(appName, appVersion, appPath);
}catch(Exception ex){
String msg = "Could not parse application related expression: " + expression;
log.error(msg);
throw new UnableToParseException(msg,ex);
}
}
//Removes unwanted characters
private String filter(String str){
return str.replace(')', ' ').replace(',',' ').trim();
}
private void parse() throws UnableToParseException {
boolean parsed = false;
for (int i = 0; i < OPERATORS.length; i++){
String[] parts = expression.split(OPERATORS[i]);
if ( parts.length == 2 && parts[1].charAt(0)!='=' && parts[0].charAt(parts[0].length()-1) != '>'){
attribute = parts[0].trim();
if (!isValidAttribute(attribute)){
String msg = "Unknown attribute " + attribute + ". Check the VMI definition language syntax.";
log.error(msg);
throw new UnableToParseException(msg);
}
operator = OPERATORS[i];
value = parts[1].replace('\'', ' ').trim();
parsed = true;
break;
}
}
if (!parsed) throw new UnableToParseException("Unable to parse expression: " + expression);
}
public String toString(){
String str;
str = isSoft() ? ("soft " + this.rankValue + " ") : "";
if (this.attribute.equals("disk.applications")){
Application app = (Application) this.value;
str += "disk.applications contains (name = " + app.getName() + ", version " + this.operator + " " + app.getVersion() + ", path = " + app.getPath() + ")";
} else{
str += this.attribute + " " + this.operator + " " + this.value;
}
return str;
}
public String toHQLClause(){
/**
* We don't want to generate HQL code for the soft attributes and for the attributes which might involve complex version numberings
* Since we can't compare version numbers through SQL, we have to programmatically do this
*/
if ( isSoft() ||
this.attribute.equals("disk.applications") ||
this.attribute.equals("disk.os.version"))
return null;
else
return htLangMap.get(this.attribute) + " " + this.operator + " '" + this.value + "'";
}
}