Package org.teiid.query.metadata

Source Code of org.teiid.query.metadata.TransformationMetadata

/*
* 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.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.jboss.virtual.VirtualFile;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.types.BlobImpl;
import org.teiid.core.types.ClobImpl;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.types.InputStreamFactory;
import org.teiid.core.types.SQLXMLImpl;
import org.teiid.core.util.ArgCheck;
import org.teiid.core.util.LRUCache;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.StringUtil;
import org.teiid.metadata.AbstractMetadataRecord;
import org.teiid.metadata.Column;
import org.teiid.metadata.ColumnSet;
import org.teiid.metadata.Datatype;
import org.teiid.metadata.ForeignKey;
import org.teiid.metadata.KeyRecord;
import org.teiid.metadata.Procedure;
import org.teiid.metadata.ProcedureParameter;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
import org.teiid.metadata.BaseColumn.NullType;
import org.teiid.metadata.Column.SearchType;
import org.teiid.metadata.ProcedureParameter.Type;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.function.FunctionTree;
import org.teiid.query.mapping.relational.QueryNode;
import org.teiid.query.mapping.xml.MappingDocument;
import org.teiid.query.mapping.xml.MappingLoader;
import org.teiid.query.mapping.xml.MappingNode;
import org.teiid.query.sql.lang.SPParameter;


/**
* Teiid's implementation of the QueryMetadataInterface that reads columns, groups, models etc.
* from the metadata object model.
*/
public class TransformationMetadata extends BasicQueryMetadata implements Serializable {
 
  private final class LiveQueryNode extends QueryNode {
    Procedure p;
    private LiveQueryNode(Procedure p) {
      super(null);
      this.p = p;
    }

    public String getQuery() {
      return p.getQueryPlan();
    }
  }

  private final class VirtualFileInputStreamFactory extends
      InputStreamFactory {
    private final VirtualFile f;

    private VirtualFileInputStreamFactory(VirtualFile f) {
      this.f = f;
    }

    @Override
    public InputStream getInputStream() throws IOException {
      return f.openStream();
    }
   
    @Override
    public long getLength() {
      try {
        return f.getSize();
      } catch (IOException e) {
      }
      return super.getLength();
    }
   
    @Override
    public void free() throws IOException {
      f.close();
    }
  }

  public static class Resource {
    public Resource(VirtualFile file, boolean visible) {
      this.file = file;
      this.visible = visible;
    }
    VirtualFile file;
    boolean visible;
  }
 
  private static final long serialVersionUID = 1058627332954475287L;
 
  /** Delimiter character used when specifying fully qualified entity names */
    public static final char DELIMITER_CHAR = StringUtil.Constants.DOT_CHAR;
    public static final String DELIMITER_STRING = String.valueOf(DELIMITER_CHAR);
   
    // error message cached to avoid i18n lookup each time
    public static String NOT_EXISTS_MESSAGE = StringUtil.Constants.SPACE+QueryPlugin.Util.getString("TransformationMetadata.does_not_exist._1"); //$NON-NLS-1$

    private static Properties EMPTY_PROPS = new Properties();
   
    private final CompositeMetadataStore store;
    private Map<String, Resource> vdbEntries;
    private FunctionLibrary functionLibrary;
    private VDBMetaData vdbMetaData;
   
    /*
     * TODO: move caching to jboss cache structure
     */
    private Map<String, Object> metadataCache = Collections.synchronizedMap(new LRUCache<String, Object>(250));
    private Map<String, Object> groupInfoCache = Collections.synchronizedMap(new LRUCache<String, Object>(250));
    private Map<String, Collection<Table>> partialNameToFullNameCache = Collections.synchronizedMap(new LRUCache<String, Collection<Table>>(1000));
    private Map<String, Collection<StoredProcedureInfo>> procedureCache = Collections.synchronizedMap(new LRUCache<String, Collection<StoredProcedureInfo>>(200));
    /**
     * TransformationMetadata constructor
     * @param context Object containing the info needed to lookup metadta.
     */
    public TransformationMetadata(VDBMetaData vdbMetadata, final CompositeMetadataStore store, Map<String, Resource> vdbEntries, FunctionTree systemFunctions, Collection<FunctionTree> functionTrees) {
      ArgCheck.isNotNull(store);
      this.vdbMetaData = vdbMetadata;
        this.store = store;
        if (vdbEntries == null) {
          this.vdbEntries = Collections.emptyMap();
        } else {
          this.vdbEntries = vdbEntries;
        }
        if (functionTrees == null) {
          this.functionLibrary = new FunctionLibrary(systemFunctions);
        } else {
            this.functionLibrary = new FunctionLibrary(systemFunctions, functionTrees.toArray(new FunctionTree[functionTrees.size()]));
        }
    }
   
    private TransformationMetadata(final CompositeMetadataStore store, FunctionLibrary functionLibrary) {
      ArgCheck.isNotNull(store);
        this.store = store;
      this.vdbEntries = Collections.emptyMap();
        this.functionLibrary = functionLibrary;
    }
   
    //==================================================================================
    //                     I N T E R F A C E   M E T H O D S
    //==================================================================================

    public Object getElementID(final String elementName) throws TeiidComponentException, QueryMetadataException {
      int columnIndex = elementName.lastIndexOf(TransformationMetadata.DELIMITER_STRING);
    if (columnIndex == -1) {
      throw new QueryMetadataException(elementName+TransformationMetadata.NOT_EXISTS_MESSAGE);
    }
    Table table = this.store.findGroup(elementName.substring(0, columnIndex).toUpperCase());
    String shortElementName = elementName.substring(columnIndex + 1);
    for (Column column : (List<Column>)getElementIDsInGroupID(table)) {
      if (column.getName().equalsIgnoreCase(shortElementName)) {
        return column;
      }
        }
        throw new QueryMetadataException(elementName+TransformationMetadata.NOT_EXISTS_MESSAGE);
    }

    public Table getGroupID(final String groupName) throws TeiidComponentException, QueryMetadataException {
        return getMetadataStore().findGroup(groupName.toUpperCase());
    }
   
    public Collection<String> getGroupsForPartialName(final String partialGroupName)
        throws TeiidComponentException, QueryMetadataException {
    ArgCheck.isNotEmpty(partialGroupName);

    Collection<Table> matches = this.partialNameToFullNameCache.get(partialGroupName);
   
    if (matches == null) {
          matches = getMetadataStore().getGroupsForPartialName(partialGroupName);
         
          this.partialNameToFullNameCache.put(partialGroupName, matches);
    }
   
    if (matches.isEmpty()) {
      return Collections.emptyList();
    }
   
    Collection<String> filteredResult = new ArrayList<String>(matches.size());
    for (Table table : matches) {
      if (vdbMetaData == null || vdbMetaData.isVisible(table.getParent().getName())) {
            filteredResult.add(table.getFullName());
          }
    }
    return filteredResult;
    }

    public Object getModelID(final Object groupOrElementID) throws TeiidComponentException, QueryMetadataException {
      ArgCheck.isInstanceOf(AbstractMetadataRecord.class, groupOrElementID);
        AbstractMetadataRecord metadataRecord = (AbstractMetadataRecord) groupOrElementID;
        AbstractMetadataRecord parent = metadataRecord.getParent();
        if (parent instanceof Schema) {
          return parent;
        }
        if (parent == null) {
          throw createInvalidRecordTypeException(groupOrElementID);
        }
        parent = parent.getParent();
        if (parent instanceof Schema) {
          return parent;
        }
      throw createInvalidRecordTypeException(groupOrElementID);
    }

    public String getFullName(final Object metadataID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
        AbstractMetadataRecord metadataRecord = (AbstractMetadataRecord) metadataID;
        return metadataRecord.getFullName();
    }
   
    @Override
    public String getName(Object metadataID) throws TeiidComponentException,
        QueryMetadataException {
      ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
        AbstractMetadataRecord metadataRecord = (AbstractMetadataRecord) metadataID;
        return metadataRecord.getName();
    }

    public List getElementIDsInGroupID(final Object groupID) throws TeiidComponentException, QueryMetadataException {
      ArgCheck.isInstanceOf(Table.class, groupID);
      return ((Table)groupID).getColumns();
    }

    public Object getGroupIDForElementID(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            Column columnRecord = (Column) elementID;
            AbstractMetadataRecord parent = columnRecord.getParent();
            if (parent instanceof Table) {
              return parent;
            }
        }
        throw createInvalidRecordTypeException(elementID);
    }
   
    public boolean hasProcedure(String name) throws TeiidComponentException {
      try {
        return getStoredProcInfoDirect(name) != null;
      } catch (QueryMetadataException e) {
        return true;
      }
    }

    public StoredProcedureInfo getStoredProcedureInfoForProcedure(final String name)
        throws TeiidComponentException, QueryMetadataException {
        StoredProcedureInfo result = getStoredProcInfoDirect(name);
       
    if (result == null) {
      throw new QueryMetadataException(name+NOT_EXISTS_MESSAGE);
    }
     
        return result;
    }

  private StoredProcedureInfo getStoredProcInfoDirect(
      final String name)
      throws TeiidComponentException, QueryMetadataException {
    ArgCheck.isNotEmpty(name);
        String canonicalName = name.toUpperCase();
        Collection<StoredProcedureInfo> results = this.procedureCache.get(canonicalName);
       
        if (results == null) {
          Collection<Procedure> procRecords = getMetadataStore().getStoredProcedure(canonicalName);
          results = new ArrayList<StoredProcedureInfo>(procRecords.size());
          for (Procedure procRecord : procRecords) {
                String procedureFullName = procRecord.getFullName();

                // create the storedProcedure info object that would hold procedure's metadata
                StoredProcedureInfo procInfo = new StoredProcedureInfo();
                procInfo.setProcedureCallableName(procedureFullName);
                procInfo.setProcedureID(procRecord);

                // modelID for the procedure
                procInfo.setModelID(procRecord.getParent());

                // get the parameter metadata info
                for (ProcedureParameter paramRecord : procRecord.getParameters()) {
                    String runtimeType = paramRecord.getRuntimeType();
                    int direction = this.convertParamRecordTypeToStoredProcedureType(paramRecord.getType());
                    // create a parameter and add it to the procedure object
                    SPParameter spParam = new SPParameter(paramRecord.getPosition(), direction, paramRecord.getFullName());
                    spParam.setMetadataID(paramRecord);
                    spParam.setClassType(DataTypeManager.getDataTypeClass(runtimeType));
                    procInfo.addParameter(spParam);
                }

                // if the procedure returns a resultSet, obtain resultSet metadata
                if(procRecord.getResultSet() != null) {
                    ColumnSet<Procedure> resultRecord = procRecord.getResultSet();
                    // resultSet is the last parameter in the procedure
                    int lastParamIndex = procInfo.getParameters().size() + 1;
                    SPParameter param = new SPParameter(lastParamIndex, SPParameter.RESULT_SET, resultRecord.getFullName());
                    param.setClassType(java.sql.ResultSet.class);          
                    param.setMetadataID(resultRecord);

                    for (Column columnRecord : resultRecord.getColumns()) {
                        String colType = columnRecord.getRuntimeType();
                        param.addResultSetColumn(columnRecord.getFullName(), DataTypeManager.getDataTypeClass(colType), columnRecord);
                    }

                    procInfo.addParameter(param);           
                }

                // if this is a virtual procedure get the procedure plan
                if(procRecord.isVirtual()) {
                    QueryNode queryNode = new LiveQueryNode(procRecord);
                    procInfo.setQueryPlan(queryNode);
                }
               
                //subtract 1, to match up with the server
                procInfo.setUpdateCount(procRecord.getUpdateCount() -1);
        results.add(procInfo);
      }
          this.procedureCache.put(canonicalName, results);         
        }
       
        StoredProcedureInfo result = null;
       
        for (StoredProcedureInfo storedProcedureInfo : results) {
          Schema schema = (Schema)storedProcedureInfo.getModelID();
          if(name.equalsIgnoreCase(storedProcedureInfo.getProcedureCallableName()) || vdbMetaData == null || vdbMetaData.isVisible(schema.getName())){
            if (result != null) {
            throw new QueryMetadataException(QueryPlugin.Util.getString("ambiguous_procedure", name)); //$NON-NLS-1$
          }
            result = storedProcedureInfo;
          }
    }
    return result;
  }
   
    /**
     * Method to convert the parameter type returned from a ProcedureParameterRecord
     * to the parameter type expected by StoredProcedureInfo
     * @param parameterType
     * @return
     */
    private int convertParamRecordTypeToStoredProcedureType(final ProcedureParameter.Type parameterType) {
        switch (parameterType) {
            case In : return SPParameter.IN;
            case Out : return SPParameter.OUT;
            case InOut : return SPParameter.INOUT;
            case ReturnValue : return SPParameter.RETURN_VALUE;
            default :
                return -1;
        }
    }

    public String getElementType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getRuntimeType();           
        } else if(elementID instanceof ProcedureParameter){
            return ((ProcedureParameter) elementID).getRuntimeType();
        } else {
            throw createInvalidRecordTypeException(elementID);
        }
    }

    public Object getDefaultValue(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getDefaultValue();           
        } else if(elementID instanceof ProcedureParameter){
            return ((ProcedureParameter) elementID).getDefaultValue();
        } else {
            throw createInvalidRecordTypeException(elementID);
        }
    }

    public Object getMinimumValue(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getMinimumValue();           
        } else if(elementID instanceof ProcedureParameter){
            return null;
        } else {
            throw createInvalidRecordTypeException(elementID);
        }
    }

    public Object getMaximumValue(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getMaximumValue();           
        } else if(elementID instanceof ProcedureParameter){
            return null;
        } else {
            throw createInvalidRecordTypeException(elementID);
        }
    }

    public boolean isVirtualGroup(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        return ((Table) groupID).isVirtual();
    }

    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#isProcedureInputElement(java.lang.Object)
     * @since 4.2
     */
    public boolean isProcedure(final Object groupID) throws TeiidComponentException, QueryMetadataException {
      if(groupID instanceof Procedure) {
            return true;           
        }
      if(groupID instanceof Table){
            return false;
        }
      throw createInvalidRecordTypeException(groupID);
    }

    public boolean isVirtualModel(final Object modelID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Schema.class, modelID);
        Schema modelRecord = (Schema) modelID;
        return !modelRecord.isPhysical();
    }

    public QueryNode getVirtualPlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);

        Table tableRecord = (Table) groupID;
        if (!tableRecord.isVirtual()) {
            throw new QueryMetadataException(QueryPlugin.Util.getString("TransformationMetadata.QueryPlan_could_not_be_found_for_physical_group__6")+tableRecord.getFullName()); //$NON-NLS-1$
        }
        String transQuery = tableRecord.getSelectTransformation();
        QueryNode queryNode = new QueryNode(transQuery);

        // get any bindings and add them onto the query node
        List bindings = tableRecord.getBindings();
        if(bindings != null) {
            for(Iterator bindIter = bindings.iterator();bindIter.hasNext();) {
                queryNode.addBinding((String)bindIter.next());
            }
        }

        return queryNode;
    }

    public String getInsertPlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
      ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecordImpl = (Table)groupID;
        if (!tableRecordImpl.isVirtual()) {
            throw new QueryMetadataException(QueryPlugin.Util.getString("TransformationMetadata.InsertPlan_could_not_be_found_for_physical_group__8")+tableRecordImpl.getFullName()); //$NON-NLS-1$
        }
        return tableRecordImpl.isInsertPlanEnabled()?tableRecordImpl.getInsertPlan():null;
    }

    public String getUpdatePlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecordImpl = (Table)groupID;
        if (!tableRecordImpl.isVirtual()) {
          throw new QueryMetadataException(QueryPlugin.Util.getString("TransformationMetadata.InsertPlan_could_not_be_found_for_physical_group__10")+tableRecordImpl.getFullName());         //$NON-NLS-1$
        }
        return tableRecordImpl.isUpdatePlanEnabled()?tableRecordImpl.getUpdatePlan():null;
    }

    public String getDeletePlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecordImpl = (Table)groupID;
        if (!tableRecordImpl.isVirtual()) {
            throw new QueryMetadataException(QueryPlugin.Util.getString("TransformationMetadata.DeletePlan_could_not_be_found_for_physical_group__12")+tableRecordImpl.getFullName()); //$NON-NLS-1$
        }
        return tableRecordImpl.isDeletePlanEnabled()?tableRecordImpl.getDeletePlan():null;
    }

    public boolean modelSupports(final Object modelID, final int modelConstant)
        throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Schema.class, modelID);

        switch(modelConstant) {
            default:
                throw new UnsupportedOperationException(QueryPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + modelConstant); //$NON-NLS-1$
        }       
    }

    public boolean groupSupports(final Object groupID, final int groupConstant)
        throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecord = (Table) groupID;

        switch(groupConstant) {
            case SupportConstants.Group.UPDATE:
                return tableRecord.supportsUpdate();
            default:
                throw new UnsupportedOperationException(QueryPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + groupConstant); //$NON-NLS-1$
        }
    }

    public boolean elementSupports(final Object elementID, final int elementConstant)
        throws TeiidComponentException, QueryMetadataException {
       
        if(elementID instanceof Column) {
            Column columnRecord = (Column) elementID;           
            switch(elementConstant) {
                case SupportConstants.Element.NULL:
                    return columnRecord.getNullType() == NullType.Nullable;
                case SupportConstants.Element.NULL_UNKNOWN:
                    return columnRecord.getNullType() == NullType.Unknown;
                case SupportConstants.Element.SEARCHABLE_COMPARE:
                    return (columnRecord.getSearchType() == SearchType.Searchable || columnRecord.getSearchType() == SearchType.All_Except_Like);
                case SupportConstants.Element.SEARCHABLE_LIKE:
                  return (columnRecord.getSearchType() == SearchType.Searchable || columnRecord.getSearchType() == SearchType.Like_Only);
                case SupportConstants.Element.SELECT:
                    return columnRecord.isSelectable();
                case SupportConstants.Element.UPDATE:
                    return columnRecord.isUpdatable();
                case SupportConstants.Element.DEFAULT_VALUE:
                    Object defaultValue = columnRecord.getDefaultValue();
                    if(defaultValue == null) {
                        return false;
                    }
                    return true;
                case SupportConstants.Element.AUTO_INCREMENT:
                    return columnRecord.isAutoIncremented();
                case SupportConstants.Element.CASE_SENSITIVE:
                    return columnRecord.isCaseSensitive();
                case SupportConstants.Element.SIGNED:
                    return columnRecord.isSigned();
                default:
                    throw new UnsupportedOperationException(QueryPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + elementConstant); //$NON-NLS-1$
            }
        } else if(elementID instanceof ProcedureParameter) {
            ProcedureParameter columnRecord = (ProcedureParameter) elementID;           
            switch(elementConstant) {
                case SupportConstants.Element.NULL:
                  return columnRecord.getNullType() == NullType.Nullable;
                case SupportConstants.Element.NULL_UNKNOWN:
                  return columnRecord.getNullType() == NullType.Unknown;
                case SupportConstants.Element.SEARCHABLE_COMPARE:
                case SupportConstants.Element.SEARCHABLE_LIKE:
                    return false;
                case SupportConstants.Element.SELECT:
                    return columnRecord.getType() != Type.In;
                case SupportConstants.Element.UPDATE:
                    return false;
                case SupportConstants.Element.DEFAULT_VALUE:
                    Object defaultValue = columnRecord.getDefaultValue();
                    if(defaultValue == null) {
                        return false;
                    }
                    return true;
                case SupportConstants.Element.AUTO_INCREMENT:
                    return false;
                case SupportConstants.Element.CASE_SENSITIVE:
                    return false;
                case SupportConstants.Element.SIGNED:
                    return true;
                default:
                    throw new UnsupportedOperationException(QueryPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + elementConstant); //$NON-NLS-1$
            }
           
        } else {           
            throw createInvalidRecordTypeException(elementID);
        }
    }
   
    private IllegalArgumentException createInvalidRecordTypeException(Object elementID) {
        return new IllegalArgumentException(QueryPlugin.Util.getString("TransformationMetadata.Invalid_type", elementID.getClass().getName()));         //$NON-NLS-1$
    }

    public int getMaxSetSize(final Object modelID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Schema.class, modelID);
        return 0;
    }

    public Collection getIndexesInGroup(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        return ((Table)groupID).getIndexes();
    }

    public Collection getUniqueKeysInGroup(final Object groupID)
        throws TeiidComponentException, QueryMetadataException {
      ArgCheck.isInstanceOf(Table.class, groupID);
      Table tableRecordImpl = (Table)groupID;
      ArrayList<ColumnSet> result = new ArrayList<ColumnSet>(tableRecordImpl.getUniqueKeys());
      if (tableRecordImpl.getPrimaryKey() != null) {
        result.add(tableRecordImpl.getPrimaryKey());
      }
      for (KeyRecord key : tableRecordImpl.getIndexes()) {
      if (key.getType() == KeyRecord.Type.Unique) {
        result.add(key);
      }
    }
      return result;
    }

    public Collection getForeignKeysInGroup(final Object groupID)
        throws TeiidComponentException, QueryMetadataException {
      ArgCheck.isInstanceOf(Table.class, groupID);
      return ((Table)groupID).getForeignKeys();
    }

    public Object getPrimaryKeyIDForForeignKeyID(final Object foreignKeyID)
        throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(ForeignKey.class, foreignKeyID);
        ForeignKey fkRecord = (ForeignKey) foreignKeyID;
        return fkRecord.getPrimaryKey();
    }

    public Collection getAccessPatternsInGroup(final Object groupID)
        throws TeiidComponentException, QueryMetadataException {
      ArgCheck.isInstanceOf(Table.class, groupID);
      return ((Table)groupID).getAccessPatterns();
    }

    public List getElementIDsInIndex(final Object index) throws TeiidComponentException, QueryMetadataException {
      ArgCheck.isInstanceOf(ColumnSet.class, index);
      return ((ColumnSet)index).getColumns();
    }

    public List getElementIDsInKey(final Object key) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(ColumnSet.class, key);
        return ((ColumnSet)key).getColumns();
    }

    public List getElementIDsInAccessPattern(final Object accessPattern)
        throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(ColumnSet.class, accessPattern);
        return ((ColumnSet)accessPattern).getColumns();
    }

    public boolean isXMLGroup(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);

        Table tableRecord = (Table) groupID;
        return tableRecord.getTableType() == Table.Type.Document;
    }

    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#hasMaterialization(java.lang.Object)
     * @since 4.2
     */
    public boolean hasMaterialization(final Object groupID) throws TeiidComponentException,
                                                      QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecord = (Table) groupID;
        return tableRecord.isMaterialized();
    }

    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#getMaterialization(java.lang.Object)
     * @since 4.2
     */
    public Object getMaterialization(final Object groupID) throws TeiidComponentException,
                                                    QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecord = (Table) groupID;
        if(tableRecord.isMaterialized()) {
          return tableRecord.getMaterializedTable();
        }
        return null;
    }

    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#getMaterializationStage(java.lang.Object)
     * @since 4.2
     */
    public Object getMaterializationStage(final Object groupID) throws TeiidComponentException,
                                                         QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecord = (Table) groupID;
        if(tableRecord.isMaterialized()) {
          return tableRecord.getMaterializedStageTable();
        }
        return null;
    }

    public MappingNode getMappingNode(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);

        Table tableRecord = (Table) groupID;
    final String groupName = tableRecord.getFullName();
        if(tableRecord.isVirtual()) {
            // get mappin transform
            String document = tableRecord.getSelectTransformation();           
            InputStream inputStream = new ByteArrayInputStream(document.getBytes());
            MappingLoader reader = new MappingLoader();
            MappingDocument mappingDoc = null;
            try{
                mappingDoc = reader.loadDocument(inputStream);
                mappingDoc.setName(groupName);
            } catch (Exception e){
                throw new TeiidComponentException(e, QueryPlugin.Util.getString("TransformationMetadata.Error_trying_to_read_virtual_document_{0},_with_body__n{1}_1", groupName, mappingDoc)); //$NON-NLS-1$
            } finally {
              try {
          inputStream.close();
              } catch(Exception e) {}
            }
            return (MappingDocument)mappingDoc.clone();
        }

        return null;
    }

    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#getVirtualDatabaseName()
     */
    public String getVirtualDatabaseName() throws TeiidComponentException, QueryMetadataException {
      if (vdbMetaData == null) {
        return null;
      }
      return vdbMetaData.getName();
    }

    public int getVirtualDatabaseVersion() {
      if (vdbMetaData == null) {
        return 0;
      }
      return vdbMetaData.getVersion();
    }
   
    public VDBMetaData getVdbMetaData() {
    return vdbMetaData;
  }
   
    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#getXMLTempGroups(java.lang.Object)
     */
    public Collection getXMLTempGroups(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecord = (Table) groupID;

        if(tableRecord.getTableType() == Table.Type.Document) {
            return this.store.getXMLTempGroups(tableRecord);
        }
        return Collections.EMPTY_SET;
    }

    public int getCardinality(final Object groupID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(Table.class, groupID);
        return ((Table) groupID).getCardinality();
    }

    public List<SQLXMLImpl> getXMLSchemas(final Object groupID) throws TeiidComponentException, QueryMetadataException {

        ArgCheck.isInstanceOf(Table.class, groupID);
        Table tableRecord = (Table) groupID;

        // lookup transformation record for the group
        String groupName = tableRecord.getFullName();

        // get the schema Paths
        List<String> schemaPaths = tableRecord.getSchemaPaths();
       
        List<SQLXMLImpl> schemas = new LinkedList<SQLXMLImpl>();
        if (schemaPaths == null) {
          return schemas;
        }
        File f = new File(tableRecord.getResourcePath());
        String path = f.getParent();
        if (File.separatorChar != '/') {
          path = path.replace(File.separatorChar, '/');
        }
        for (String string : schemaPaths) {
          String parentPath = path;
          boolean relative = false;
          while (string.startsWith("../")) { //$NON-NLS-1$
            relative = true;
            string = string.substring(3);
            parentPath = new File(parentPath).getParent();
          }
          SQLXMLImpl schema = null;
          if (!relative) {
            schema = getVDBResourceAsSQLXML(string);
          }
          if (schema == null) {
            if (!parentPath.endsWith("/")) { //$NON-NLS-1$
              parentPath += "/"; //$NON-NLS-1$
            }
            schema = getVDBResourceAsSQLXML(parentPath + string);
          }
         
          if (schema == null) {
            throw new QueryMetadataException(QueryPlugin.Util.getString("TransformationMetadata.Error_trying_to_read_schemas_for_the_document/table____1")+groupName);             //$NON-NLS-1$   
          }
          schemas.add(schema);
        }
       
        return schemas;
    }

    public String getNameInSource(final Object metadataID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
        return ((AbstractMetadataRecord) metadataID).getNameInSource();
    }

    public int getElementLength(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getLength();           
        } else if(elementID instanceof ProcedureParameter){
            return ((ProcedureParameter) elementID).getLength();
        } else {
            throw createInvalidRecordTypeException(elementID);
        }
    }

    public int getPosition(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getPosition();
        } else if(elementID instanceof ProcedureParameter) {
            return ((ProcedureParameter) elementID).getPosition();           
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }
   
    public int getPrecision(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getPrecision();
        } else if(elementID instanceof ProcedureParameter) {
            return ((ProcedureParameter) elementID).getPrecision();           
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }
   
    public int getRadix(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getRadix();
        } else if(elementID instanceof ProcedureParameter) {
            return ((ProcedureParameter) elementID).getRadix();           
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }
   
  public String getFormat(Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getFormat();
        }
        throw createInvalidRecordTypeException(elementID);           
  }      
   
    public int getScale(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getScale();
        } else if(elementID instanceof ProcedureParameter) {
            return ((ProcedureParameter) elementID).getScale();           
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }

    public int getDistinctValues(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getDistinctValues();
        } else if(elementID instanceof ProcedureParameter) {
            return -1;           
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }

    public int getNullValues(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getNullValues();
        } else if(elementID instanceof ProcedureParameter) {
            return -1;           
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }

    public String getNativeType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        if(elementID instanceof Column) {
            return ((Column) elementID).getNativeType();
        } else if(elementID instanceof ProcedureParameter) {
            return null;           
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }

    public Properties getExtensionProperties(final Object metadataID) throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
        AbstractMetadataRecord metadataRecord = (AbstractMetadataRecord) metadataID;
        Map<String, String> result = metadataRecord.getProperties();
        if (result == null) {
          return EMPTY_PROPS;
        }
        Properties p = new Properties();
        p.putAll(result);
        return p;
    }

    /**
     * @see org.teiid.query.metadata.BasicQueryMetadata#getBinaryVDBResource(java.lang.String)
     * @since 4.3
     */
    public byte[] getBinaryVDBResource(String resourcePath) throws TeiidComponentException, QueryMetadataException {
      final VirtualFile f = getFile(resourcePath);
      if (f == null) {
        return null;
      }
    try {
      return ObjectConverterUtil.convertToByteArray(f.openStream());
    } catch (IOException e) {
      throw new TeiidComponentException(e);
    }
    }
   
    public ClobImpl getVDBResourceAsClob(String resourcePath) {
      final VirtualFile f = getFile(resourcePath);
      if (f == null) {
        return null;
      }
    return new ClobImpl(new VirtualFileInputStreamFactory(f), -1);
    }
   
    public SQLXMLImpl getVDBResourceAsSQLXML(String resourcePath) {
      final VirtualFile f = getFile(resourcePath);
      if (f == null) {
        return null;
      }
    return new SQLXMLImpl(new VirtualFileInputStreamFactory(f));
    }
   
    public BlobImpl getVDBResourceAsBlob(String resourcePath) {
      final VirtualFile f = getFile(resourcePath);
      if (f == null) {
        return null;
      }
      return new BlobImpl(new VirtualFileInputStreamFactory(f));
    }
   
    private VirtualFile getFile(String resourcePath) {
      if (resourcePath == null) {
        return null;
      }
      Resource r = this.vdbEntries.get(resourcePath);
      if (r != null) {
        return r.file;
      }
      return null;
    }

    /**
     * @see org.teiid.query.metadata.BasicQueryMetadata#getCharacterVDBResource(java.lang.String)
     * @since 4.3
     */
    public String getCharacterVDBResource(String resourcePath) throws TeiidComponentException, QueryMetadataException {
      try {
        byte[] bytes = getBinaryVDBResource(resourcePath);
        if (bytes == null) {
          return null;
        }
      return ObjectConverterUtil.convertToString(new ByteArrayInputStream(bytes));
    } catch (IOException e) {
      throw new TeiidComponentException(e);
    }
    }
   
    public CompositeMetadataStore getMetadataStore() {
      return this.store;
    }

    /**
     * @see org.teiid.query.metadata.BasicQueryMetadata#getVDBResourcePaths()
     * @since 4.3
     */
    public String[] getVDBResourcePaths() throws TeiidComponentException, QueryMetadataException {
      LinkedList<String> paths = new LinkedList<String>();
      for (Map.Entry<String, Resource> entry : this.vdbEntries.entrySet()) {
      paths.add(entry.getKey());
      }
      return paths.toArray(new String[paths.size()]);
    }
   
    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#getModeledType(java.lang.Object)
     * @since 5.0
     */
    public String getModeledType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        Datatype record = getDatatypeRecord(elementID);
        if (record != null) {
            return record.getDatatypeID();
        }
        return null;
    }
   
    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#getModeledBaseType(java.lang.Object)
     * @since 5.0
     */
    public String getModeledBaseType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        Datatype record = getDatatypeRecord(elementID);
        if (record != null) {
            return record.getBasetypeID();
        }
        return null;
    }

    /**
     * @see org.teiid.query.metadata.QueryMetadataInterface#getModeledPrimitiveType(java.lang.Object)
     * @since 5.0
     */
    public String getModeledPrimitiveType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
        Datatype record = getDatatypeRecord(elementID);
        if (record != null) {
            return record.getPrimitiveTypeID();
        }
        return null;
    }

    private Datatype getDatatypeRecord(final Object elementID) {
        if (elementID instanceof Column) {
            return ((Column)elementID).getDatatype();
        } else if (elementID instanceof ProcedureParameter) {
            return ((ProcedureParameter)elementID).getDatatype();
        } else {
            throw createInvalidRecordTypeException(elementID);           
        }
    }

  @Override
  public Object addToMetadataCache(Object metadataID, String key, Object value) {
        ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
        boolean groupInfo = key.startsWith(GroupInfo.CACHE_PREFIX);
        key = getCacheKey(key, (AbstractMetadataRecord)metadataID);
        if (groupInfo) {
          return this.groupInfoCache.put(key, value);
        }
      return this.metadataCache.put(key, value);
  }

  @Override
  public Object getFromMetadataCache(Object metadataID, String key)
      throws TeiidComponentException, QueryMetadataException {
        ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
        boolean groupInfo = key.startsWith(GroupInfo.CACHE_PREFIX);
        key = getCacheKey(key, (AbstractMetadataRecord)metadataID);
        if (groupInfo) {
          return this.groupInfoCache.get(key);
        }
      return this.metadataCache.get(key);
  }

  private String getCacheKey(String key, AbstractMetadataRecord record) {
    return record.getUUID() + "/" + key; //$NON-NLS-1$
  }

  @Override
  public FunctionLibrary getFunctionLibrary() {
    return this.functionLibrary;
  }
 
  @Override
  public Object getPrimaryKey(Object metadataID) {
    ArgCheck.isInstanceOf(Table.class, metadataID);
    Table table = (Table)metadataID;
    return table.getPrimaryKey();
  }
 
  @Override
  public QueryMetadataInterface getDesignTimeMetadata() {
    TransformationMetadata tm = new TransformationMetadata(store, functionLibrary);
    tm.groupInfoCache = this.groupInfoCache;
    tm.metadataCache = this.metadataCache;
    tm.partialNameToFullNameCache = this.partialNameToFullNameCache;
    tm.procedureCache = this.procedureCache;
    return tm;
  }
}
TOP

Related Classes of org.teiid.query.metadata.TransformationMetadata

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.