/*
* Copyright (C) 2008-2012 Steve Ratcliffe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* Author: Steve Ratcliffe
* Create date: 03-Nov-2008
*/
package uk.me.parabola.mkgmap.osmstyle.eval;
import uk.me.parabola.imgfmt.ExitException;
import uk.me.parabola.mkgmap.reader.osm.Element;
import uk.me.parabola.mkgmap.scan.SyntaxException;
/**
* A base class that can be used as the superclass of an operation.
*
* @author Steve Ratcliffe
*/
public abstract class AbstractOp implements Op {
protected Op first;
private NodeType type;
protected boolean lastRes;
protected int lastCachedId = -1;
public static Op createOp(String value) {
char c = value.charAt(0);
Op op;
switch (c) {
case '=': op = new EqualsOp(); break;
case '&':
if (value.length() > 1)
throw new SyntaxException(String.format("Use '&' instead of '%s'", value));
op = new AndOp();
break;
case '|':
if (value.length() > 1)
throw new SyntaxException(String.format("Use '|' instead of '%s'", value));
op = new OrOp();
break;
case '~': op = new RegexOp(); break;
case '(': op = new OpenOp(); break;
case ')': op = new CloseOp(); break;
case '>':
if (value.equals(">="))
op = new GTEOp();
else
op = new GTOp();
break;
case '<':
if (value.equals("<="))
op = new LTEOp();
else
op = new LTOp();
break;
case '!':
if (value.equals("!="))
op = new NotEqualOp();
else
op = new NotOp();
break;
default:
throw new SyntaxException("Unrecognised operation " + c);
}
return op;
}
public boolean eval(int cacheId, Element el){
if (lastCachedId != cacheId){
if (lastCachedId > cacheId){
throw new ExitException("fatal error: cache id invalid");
}
lastRes = eval(el);
lastCachedId = cacheId;
}
return lastRes;
}
/**
* Does this operation have a higher priority that the other one?
* @param other The other operation.
*/
public boolean hasHigherPriority(Op other) {
return priority() > other.priority();
}
public Op getFirst() {
return first;
}
public void setFirst(Op first) {
this.first = first;
lastCachedId = -1;
}
/**
* Only supported on Binary operations, but useful to return null to make code simpler, rather than
* defaulting to UnsupportedOperation.
*/
public Op getSecond() {
return null;
}
public NodeType getType() {
return type;
}
protected void setType(NodeType type) {
this.type = type;
}
/**
* Only supported on value nodes.
*/
public String value(Element el) {
throw new UnsupportedOperationException();
}
/**
* This is only supported on value nodes.
*/
public String getKeyValue() {
throw new UnsupportedOperationException();
}
public boolean isType(NodeType value) {
return type == value;
}
public void resetCache(){
lastCachedId = -1;
}
}