package com.tesora.dve.sql.expression;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.util.Collection;
import com.tesora.dve.common.PEConstants;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.TransformException;
import com.tesora.dve.sql.ParserException.Pass;
import com.tesora.dve.sql.transform.CopyContext;
public abstract class Traversable {
protected Traversable parent;
public Traversable getParent() {
return parent;
}
public void setParent(Traversable t) {
parent = t;
}
protected void setParentOf(Traversable that) {
if (that != null)
that.setParent(this);
}
protected void setParentOf(Collection<? extends Traversable> those) {
if (those == null)
return;
for(Traversable t : those)
setParentOf(t);
}
public void replace(Traversable prev, Traversable nv) {
if (!replaceTraversable(prev, nv))
throw new TransformException(Pass.REWRITER, "Unable to replace " + prev + " with " + nv + " in " + this);
}
public boolean replaceTraversable(Traversable prev, Traversable nv) {
throw new IllegalStateException("Cannot replace in " + this.getClass().getName());
}
public Traversable copy(CopyContext cc) {
throw new IllegalArgumentException("No copy support for " + this.getClass().getName());
}
public boolean hasAncestorsAmong(Collection<Traversable> ancestors) {
if (parent == null)
return false;
if (ancestors.contains(parent))
return true;
else
return parent.hasAncestorsAmong(ancestors);
}
@SuppressWarnings("unchecked")
public <T extends Traversable> T ifAncestor(Collection<T> any) {
if (any.contains(this))
return (T)this;
else if (parent == null)
return null;
else
return parent.ifAncestor(any);
}
public String dumpAncestorChain() {
StringBuffer buf = new StringBuffer();
Traversable t = this;
int l = 0;
while(t != null) {
buf.append("a[").append(l).append("]: ").append(t).append(PEConstants.LINE_SEPARATOR);
l++;
t = t.getParent();
}
return buf.toString();
}
public Traversable getEnclosing(Class<?> searchFor, Class<?> stopAt) {
Traversable p = this;
while(p != null) {
if (searchFor.isInstance(p))
return p;
else if (stopAt != null && stopAt.isInstance(p))
return null;
p = p.getParent();
}
return null;
}
public int getSchemaHashCode() {
throw new SchemaException(Pass.REWRITER, "No schema hash available for " + getClass().getName());
}
public boolean schemaEqual(Traversable other) {
throw new SchemaException(Pass.REWRITER, "No schema equality available for " + getClass().getName());
}
protected int addSchemaHash(int result, Traversable in) {
return addSchemaHash(result, (in == null ? 0 : in.getSchemaHashCode()));
}
protected int addSchemaHash(int result, boolean v) {
return addSchemaHash(result, (v ? 1231 : 1237));
}
protected int addSchemaHash(int result, int hc) {
final int prime = 31;
return prime * result + hc;
}
}