/* * 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.metadata; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.NavigableMap; import java.util.TreeMap; import org.teiid.query.metadata.TempMetadataID.Type; import org.teiid.query.sql.symbol.AliasSymbol; import org.teiid.query.sql.symbol.ElementSymbol; import org.teiid.query.sql.symbol.Expression; import org.teiid.query.sql.symbol.ExpressionSymbol; import org.teiid.query.sql.symbol.Reference; import org.teiid.query.sql.symbol.Symbol; /** * Store for temporary metadata discovering while resolving a query. */ public class TempMetadataStore implements Serializable { private static final long serialVersionUID = 4055072385672022478L; // UPPER CASE TEMP GROUP NAME --> TempMetadataID for group private NavigableMap<String, TempMetadataID> tempGroups; /** * Constructor for TempMetadataStore. */ public TempMetadataStore() { this(new TreeMap<String, TempMetadataID>(String.CASE_INSENSITIVE_ORDER)); } /** * Constructor for TempMetadataStore that takes a set of data to use. If * the parameter is null, a new empty Map will beused instead. * @param data Map of upper case group name to group TempMetadataID object */ public TempMetadataStore(NavigableMap<String, TempMetadataID> data) { if (data == null) { tempGroups = new TreeMap<String, TempMetadataID>(String.CASE_INSENSITIVE_ORDER); } else { tempGroups = data; } } public TempMetadataStore clone() { TreeMap<String, TempMetadataID> clone = new TreeMap<String, TempMetadataID>(String.CASE_INSENSITIVE_ORDER); clone.putAll(tempGroups); return new TempMetadataStore(clone); } /** * Get all temp group and element metadata * @param data Map of upper case group name to group TempMetadataID object */ public NavigableMap<String, TempMetadataID> getData() { return this.tempGroups; } /** * Add a temp group and all it's elements * @param tempGroup Name of temp group * @param tempSymbols List of ElementSymbol in position order */ public TempMetadataID addTempGroup(String tempGroup, List tempSymbols) { return addTempGroup(tempGroup, tempSymbols, true); } /** * Add a temp group and all it's elements * @param tempGroup Name of temp group * @param tempSymbols List of ElementSymbol in position order * @param isVirtual whether or not the group is a virtual group */ public TempMetadataID addTempGroup(String tempGroup, List tempSymbols, boolean isVirtual) { return addTempGroup(tempGroup, tempSymbols, isVirtual, false); } /** * Add a temp group and all it's elements * @param tempGroup Name of temp group * @param tempGroupDefinition optional definition if the tempGroup * param is the aliased name of a group * @param tempSymbols List of ElementSymbol in position order * @param isVirtual whether or not the group is a virtual group * @param isTempTable whether or not the group is a temporary table */ public TempMetadataID addTempGroup(String tempGroup, List<? extends Expression> tempSymbols, boolean isVirtual, boolean isTempTable) { // Add the temporary group List<TempMetadataID> elementIDs = new ArrayList<TempMetadataID>(tempSymbols.size()); for (Expression symbol : tempSymbols) { TempMetadataID elementID = createElementSymbol(tempGroup, symbol, isTempTable); elementIDs.add(elementID); } // Create group ID TempMetadataID groupID = new TempMetadataID(tempGroup, elementIDs, isVirtual?Type.VIRTUAL:Type.TEMP); this.tempGroups.put(tempGroup, groupID); return groupID; } private TempMetadataID createElementSymbol(String tempName, Expression symbol, boolean isTempTable) { // Create new element name String elementName = tempName + Symbol.SEPARATOR + Symbol.getShortName(symbol); Object metadataID = null; if (symbol instanceof AliasSymbol) { AliasSymbol as = (AliasSymbol)symbol; symbol = as.getSymbol(); } //the following allows for original metadata ids to be determined for proc inputs if (symbol instanceof ExpressionSymbol) { Expression expr = ((ExpressionSymbol)symbol).getExpression(); if (expr instanceof Reference) { expr = ((Reference)expr).getExpression(); } if (expr instanceof ElementSymbol) { symbol = expr; } } if (symbol instanceof ElementSymbol) { metadataID = ((ElementSymbol)symbol).getMetadataID(); } while (metadataID != null && metadataID instanceof TempMetadataID) { metadataID = ((TempMetadataID)metadataID).getOriginalMetadataID(); } TempMetadataID elementID = new TempMetadataID(elementName, symbol.getType(), metadataID); elementID.setTempTable(isTempTable); return elementID; } /** * Add a element symbol to the already created temp group. If added successfully then it will * return the metadata id for the added element. otherwise it will return null. * @param tempGroup - temp group name * @param symbol - element to be added * @return metadata id. */ public TempMetadataID addElementSymbolToTempGroup(String tempGroup, Expression symbol) { TempMetadataID groupID = this.tempGroups.get(tempGroup); if (groupID != null) { TempMetadataID elementID = createElementSymbol(tempGroup, symbol, false); groupID.addElement(elementID); return elementID; } return null; } /** * Get temporary group ID based on group name * @param tempGroup Group name * @return Metadata ID or null if not found */ public TempMetadataID getTempGroupID(String tempGroup) { return tempGroups.get(tempGroup); } /** * Get temporary element ID based on full element name * @param tempElement Element name * @return Metadata ID or null if not found */ public TempMetadataID getTempElementID(String tempElement) { int index = tempElement.lastIndexOf(Symbol.SEPARATOR); if(index < 0) { return null; } String groupName = tempElement.substring(0, index); TempMetadataID groupID = tempGroups.get(groupName); if(groupID != null) { for (TempMetadataID elementID : groupID.getElements()) { if(elementID.getID().equalsIgnoreCase(tempElement)) { return elementID; } } } return null; } /** * Get temporary element ID based on group and element name parts * @param tempGroup Group name * @param tempElement Short element name * @return Metadata ID or null if not found */ public List<TempMetadataID> getTempElementElementIDs(String tempGroup) { TempMetadataID groupID = getTempGroupID(tempGroup); if(groupID != null) { return groupID.getElements(); } return null; } public void addElementToTempGroup(String tempGroup, ElementSymbol symbol) { TempMetadataID groupID = tempGroups.get(tempGroup); if(groupID != null) { groupID.addElement((TempMetadataID)symbol.getMetadataID()); } } public TempMetadataID removeTempGroup(String tempGroup) { return tempGroups.remove(tempGroup); } }