/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.query.sql.symbol; import org.teiid.core.util.HashCodeUtil; import org.teiid.query.sql.LanguageVisitor; /** * <p>This is a subclass of Symbol representing a single element. An ElementSymbol * also is an expression and thus has a type. Element symbols have a variety of * attributes that determine how they are displayed - a flag for displaying fully qualified * and an optional vdb name.</p> * * <p>The "isExternalReference" property indicates whether the element symbol * refers to an element from a group outside the current command. Typically this * is set to false. Common uses when this is set to true are for variables used * within a command, correlated elements within a command, etc. </p> */ public class ElementSymbol extends Symbol implements DerivedExpression { public enum DisplayMode { FULLY_QUALIFIED, // symbol name OUTPUT_NAME, // default SHORT_OUTPUT_NAME} private GroupSymbol groupSymbol; private Object metadataID; private Class<?> type; private boolean isExternalReference; private boolean isAggregate; private DisplayMode displayMode = DisplayMode.OUTPUT_NAME; /** * Simple constructor taking just a name. By default will display fully qualified name * @param name Name of the symbol, may or may not be fully qualified */ public ElementSymbol(String name) { super(name); } public ElementSymbol(String shortName, GroupSymbol group) { this(shortName, group, null); } public ElementSymbol(String shortName, GroupSymbol group, Class<?> type) { this.setShortName(shortName); this.groupSymbol = group; this.type = type; } /** * Constructor taking a name and a flag whether to display fully qualified. * @param name Name of the symbol * @param displayFullyQualified True if should display fully qualified */ public ElementSymbol(String name, boolean displayFullyQualified) { super(name); setDisplayFullyQualified(displayFullyQualified); } @Override public String getName() { if (this.groupSymbol != null) { return this.groupSymbol.getName() + Symbol.SEPARATOR + this.getShortName(); } return super.getName(); } @Override public boolean equals(Object obj) { if (this.groupSymbol == null) { return super.equals(obj); } if (obj == this) { return true; } if (!(obj instanceof ElementSymbol)) { return false; } ElementSymbol other = (ElementSymbol)obj; if (other.groupSymbol == null) { return super.equals(obj); } return this.groupSymbol.equals(other.groupSymbol) && this.getShortName().equals(other.getShortName()); } @Override public int hashCode() { if (this.groupSymbol != null) { return HashCodeUtil.hashCode(this.groupSymbol.hashCode(), this.getShortName().hashCode()); } return super.hashCode(); } public void setDisplayMode(DisplayMode displayMode) { if (displayMode == null) { this.displayMode = DisplayMode.OUTPUT_NAME; } this.displayMode = displayMode; } public DisplayMode getDisplayMode() { return displayMode; } /** * Set whether this element will be displayed as fully qualified * @param displayFullyQualified True if should display fully qualified */ public void setDisplayFullyQualified(boolean displayFullyQualified) { this.displayMode = displayFullyQualified?DisplayMode.FULLY_QUALIFIED:DisplayMode.SHORT_OUTPUT_NAME; } /** * Get whether this element will be displayed as fully qualified * @return True if should display fully qualified */ public boolean getDisplayFullyQualified() { return this.displayMode.equals(DisplayMode.FULLY_QUALIFIED); } /** * Set whether this element is an external reference. An external * reference is an element that comes from a group outside the current * command context. Typical uses would be variables and correlated * references in subqueries. * @param isExternalReference True if element is an external reference */ public void setIsExternalReference(boolean isExternalReference) { this.isExternalReference = isExternalReference; } /** * Get whether this element is an external reference to a group * outside the command context. * @return True if element is an external reference */ public boolean isExternalReference() { return this.isExternalReference; } /** * Set the group symbol referred to by this element symbol * @param symbol the group symbol to set */ public void setGroupSymbol(GroupSymbol symbol) { this.groupSymbol = symbol; } protected void setName(String name) { int index = name.lastIndexOf('.'); if (index > 0) { if (this.groupSymbol != null) { throw new AssertionError("Attempt to set an invalid name"); //$NON-NLS-1$ } GroupSymbol gs = new GroupSymbol(new String(name.substring(0, index))); this.setGroupSymbol(gs); name = new String(name.substring(index + 1)); } else { this.groupSymbol = null; } super.setShortName(name); } /** * Get the group symbol referred to by this element symbol, may be null before resolution * @return Group symbol referred to by this element, may be null */ public GroupSymbol getGroupSymbol() { return this.groupSymbol; } /** * Get the metadata ID reference * @return Metadata ID reference, may be null before resolution */ public Object getMetadataID() { return this.metadataID; } /** * Set the metadata ID reference for this element * @param metadataID Metadata ID reference */ public void setMetadataID(Object metadataID) { this.metadataID = metadataID; } /** * Get the type of the symbol * @return Type of the symbol, may be null before resolution */ public Class<?> getType() { return this.type; } /** * Set the type of the symbol * @param type New type */ public void setType(Class<?> type) { this.type = type; } public void acceptVisitor(LanguageVisitor visitor) { visitor.visit(this); } /** * Return a deep copy of this object. * @return Deep copy of this object */ public ElementSymbol clone() { ElementSymbol copy = new ElementSymbol(getShortName(), null); if(getGroupSymbol() != null) { copy.setGroupSymbol(getGroupSymbol().clone()); } copy.setMetadataID(getMetadataID()); copy.setType(getType()); copy.setIsExternalReference(isExternalReference()); copy.outputName = this.outputName; copy.setDisplayMode(this.getDisplayMode()); copy.isAggregate = isAggregate; return copy; } public boolean isAggregate() { return isAggregate; } public void setAggregate(boolean isAggregate) { this.isAggregate = isAggregate; } }