Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.olingo.service;
 
 import static org.teiid.language.visitor.SQLStringVisitor.getRecordName;
 
 import java.util.List;
 import java.util.Map;
 
 
 public class OData4EntitySchemaBuilder {
 
     public static CsdlSchema buildMetadata(String namespaceorg.teiid.metadata.Schema teiidSchema) {
         try {
             CsdlSchema edmSchema = new CsdlSchema();
             buildEntityTypes(namespaceteiidSchemaedmSchema);
             buildProcedures(teiidSchemaedmSchema);
             return edmSchema;
         } catch (Exception e) {
             throw new TeiidRuntimeException(e);
         }
     }
 
     static CsdlEntitySet findEntitySet(CsdlSchema edmSchemaString enitityName) {
         CsdlEntityContainer entityContainter = edmSchema.getEntityContainer();
         for (CsdlEntitySet entitySet : entityContainter.getEntitySets()) {
             if (entitySet.getName().equalsIgnoreCase(enitityName)) {
                 return entitySet;
             }
         }
         return null;
     }
 
     static CsdlSchema findSchema(Map<StringCsdlSchemaedmSchemasString schemaName) {
         return edmSchemas.get(schemaName);
     }
 
     static CsdlEntityType findEntityType(Map<StringCsdlSchemaedmSchemasString schemaNameString enitityName) {
         CsdlSchema schema = findSchema(edmSchemasschemaName);
         if (schema != null) {
             for (CsdlEntityType type : schema.getEntityTypes()) {
                 if (type.getName().equalsIgnoreCase(enitityName)) {
                     return type;
                 }
             }
         }
         return null;
     }
 
     static CsdlEntityContainer findEntityContainer(Map<StringCsdlSchemaedmSchemasString schemaName) {
         CsdlSchema schema = edmSchemas.get(schemaName);
         return schema.getEntityContainer();
     }
 
     static void buildEntityTypes(String namespaceorg.teiid.metadata.Schema schemaCsdlSchema edmSchema) {
         Map<StringCsdlEntitySetentitySets = new LinkedHashMap<StringCsdlEntitySet>();
         Map<StringCsdlEntityTypeentityTypes = new LinkedHashMap<StringCsdlEntityType>();
         
         String fullSchemaName = namespace+"."+schema.getName();
 
        for (Table table : schema.getTables().values()) {
            // skip if the table does not have the PK or unique
            KeyRecord primaryKey = getIdentifier(table);
            if ( primaryKey == null) {
                LogManager.logDetail(.,..gs(..,table.getFullName()));
                continue;
            }
            String entityTypeName = table.getName();
            CsdlEntityType entityType = new CsdlEntityType().setName(entityTypeName);
            // adding properties
            List<CsdlPropertyproperties = new ArrayList<CsdlProperty>();
            for (Column c : table.getColumns()) {
                properties.add(buildProperty(cisPartOfPrimaryKey(tablec.getName())?false:(c.getNullType() == .)));
            }
            entityType.setProperties(properties);
            if (hasStream(properties)) {
                entityType.setHasStream(true);
            }
            // set keys
            ArrayList<CsdlPropertyRefkeyProps = new ArrayList<CsdlPropertyRef>();
            for (Column c : primaryKey.getColumns()) {
                keyProps.add(new CsdlPropertyRef().setName(c.getName()));
            }
            entityType.setKey(keyProps);
            // entity set one for one entity type
            CsdlEntitySet entitySet = new CsdlEntitySet()
                    .setName(table.getName())
                    .setType(new FullQualifiedName(fullSchemaNametable.getName()))
                    .setIncludeInServiceDocument(true);
           
            // add entity types for entity schema
            entityTypes.put(entityTypeNameentityType);
            entitySets.put(entityTypeNameentitySet);
        }
        
        buildNavigationProperties(schemaentityTypesentitySets);
        // entity container is holder entity sets, association sets, function
        // imports
        CsdlEntityContainer entityContainer = new CsdlEntityContainer().setName(
                schema.getName()).setEntitySets(
                new ArrayList<CsdlEntitySet>(entitySets.values()));
        // build entity schema
        edmSchema.setNamespace(fullSchemaName).setAlias(schema.getName()) //$NON-NLS-1$
                .setEntityTypes(new ArrayList<CsdlEntityType>(entityTypes.values()))
                .setEntityContainer(entityContainer);
    }
    private static boolean hasStream(List<CsdlPropertyproperties) {
        for (CsdlProperty p : properties) {
            if (p.getType().equals(..getFullQualifiedName())) {
                return true;
            }
        }
        return false;
    }
    private static CsdlProperty buildProperty(Column cboolean nullable) {
        CsdlProperty property = new CsdlProperty()
                .setName(c.getName())
                .setType(ODataTypeManager.odataType(c.getRuntimeType()).getFullQualifiedName())
                .setNullable(nullable);
        if (DataTypeManager.isArrayType(c.getRuntimeType())) {
            property.setCollection(true);
        }
            property.setMaxLength(c.getLength()).setUnicode(true);
        } else if (c.getRuntimeType().equals(
                ..)
                || c.getRuntimeType().equals(..)
                || c.getRuntimeType().equals(..)) {
            property.setPrecision(c.getPrecision());
            property.setScale(c.getScale());
        } else {
            if (c.getDefaultValue() != null) {
                property.setDefaultValue(c.getDefaultValue());
            }
        }
        return property;
    }
    
    static boolean isPartOfPrimaryKey(Table tableString columnName) {
        KeyRecord pk = table.getPrimaryKey();
        if (hasColumn(pkcolumnName)) {
            return true;
        }
        for (KeyRecord key:table.getUniqueKeys()) {
            if (hasColumn(keycolumnName)) {
                return true;
            }            
        }
        return false;
    }
    
    static boolean hasColumn(KeyRecord pkString columnName) {
        if (pk != null) {
            for (Column column : pk.getColumns()) {
                if (getRecordName(column).equals(columnName)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private static KeyRecord getIdentifier(Table table) {
        if (table.getPrimaryKey() != null) {
            return table.getPrimaryKey();
        }
        
        for (KeyRecord key:table.getUniqueKeys()) {
            return key;
        }
        return null;
    }
    
    private static void buildNavigationProperties(org.teiid.metadata.Schema schema
            Map<StringCsdlEntityTypeentityTypesMap<StringCsdlEntitySetentitySets) {
    
        for (Table table : schema.getTables().values()) {
            // skip if the table does not have the PK or unique
            if (getIdentifier(table) == null) {
                continue;
            }
                       
            // build Associations
            for (ForeignKey fk : table.getForeignKeys()) {
    
                // check to see if fk is part of this table's pk, then it is 1 to 1 relation
                boolean onetoone = sameColumnSet(getIdentifier(table), fk);
                CsdlNavigationProperty navigaton = null;
                CsdlNavigationPropertyBinding navigationBinding = null;
                String entityTypeName = null;
                if (onetoone) {
                    entityTypeName = table.getName();
                    navigaton = buildNavigation(fk);                
                    navigationBinding = buildNavigationBinding(fk);                    
                    navigaton.setNullable(false);
                } else {
                    entityTypeName = fk.getReferenceTableName();
                    navigaton = buildReverseNavigation(tablefk);                
                    navigationBinding = buildReverseNavigationBinding(table,fk);                                        
                    navigaton.setCollection(true);
                }                
    
                
                CsdlEntityType entityType = entityTypes.get(entityTypeName);
                entityType.getNavigationProperties().add(navigaton);
                
                CsdlEntitySet entitySet = entitySets.get(entityTypeName);
                entitySet.getNavigationPropertyBindings().add(navigationBinding);                
            }
        }
    }
        CsdlNavigationPropertyBinding navigationBinding = new CsdlNavigationPropertyBinding();
        navigationBinding.setPath(fk.getName());
        navigationBinding.setTarget(fk.getReferenceTableName());
        return navigationBinding;
    }
    
        CsdlNavigationPropertyBinding navigationBinding = new CsdlNavigationPropertyBinding();
        navigationBinding.setPath(table.getName()+"_"+fk.getName());
        navigationBinding.setTarget(table.getName());
        return navigationBinding;
    }
    private static CsdlNavigationProperty buildNavigation(ForeignKey fk) {
        String refSchemaName = fk.getReferenceKey().getParent().getParent().getName();
        CsdlNavigationProperty navigaton = new CsdlNavigationProperty();
        navigaton.setName(fk.getName()).setType(new FullQualifiedName(refSchemaNamefk.getReferenceTableName()));
        
        for (int i = 0; i < fk.getColumns().size(); i++) {
            Column c = fk.getColumns().get(i);
            String refColumn = fk.getReferenceColumns().get(i);
            CsdlReferentialConstraint constraint = new CsdlReferentialConstraint();
            constraint.setProperty(c.getName());
            constraint.setReferencedProperty(refColumn);
        }
        navigaton.setReferentialConstraints(constrainsts);
        return navigaton;
    }
    
    private static CsdlNavigationProperty buildReverseNavigation(Table tableForeignKey fk) {
        String refSchemaName = table.getParent().getName();
        
        CsdlNavigationProperty navigaton = new CsdlNavigationProperty();
        navigaton.setName(table.getName()+"_"+fk.getName()).setType(new FullQualifiedName(refSchemaNametable.getName()));
        
        for (int i = 0; i < fk.getColumns().size(); i++) {
            Column c = fk.getColumns().get(i);
            String refColumn = fk.getReferenceColumns().get(i);
            CsdlReferentialConstraint constraint = new CsdlReferentialConstraint();
            constraint.setProperty(refColumn);
            constraint.setReferencedProperty(c.getName());
        }
        navigaton.setReferentialConstraints(constrainsts);
        return navigaton;
    }    
    static void buildProcedures(org.teiid.metadata.Schema schemaCsdlSchema edmSchema) {
        // procedures
        ArrayList<CsdlComplexTypecomplexTypes = new ArrayList<CsdlComplexType>();
        ArrayList<CsdlFunctionfunctions = new ArrayList<CsdlFunction>();
        ArrayList<CsdlFunctionImportfunctionImports = new ArrayList<CsdlFunctionImport>();
        ArrayList<CsdlActionactions = new ArrayList<CsdlAction>();
        ArrayList<CsdlActionImportactionImports = new ArrayList<CsdlActionImport>();
        for (Procedure proc : schema.getProcedures().values()) {
            if (!allowedProcedure(proc)){
                LogManager.logDetail(.
                        ..gs(..proc.getFullName()));
                continue;                
            }
            
            if (isFuntion(proc)) {
                buildFunction(schema.getName(), proccomplexTypesfunctionsfunctionImports);
            }
            else {
                buildAction(schema.getName(), proccomplexTypesactionsactionImports);
            }
        }
        edmSchema.setComplexTypes(complexTypes);
        edmSchema.setFunctions(functions);
        edmSchema.setActions(actions);
        edmSchema.getEntityContainer().setFunctionImports(functionImports);
        edmSchema.getEntityContainer().setActionImports(actionImports);
    }
    private static boolean doesProcedureReturn(Procedure proc) {        
        for (ProcedureParameter pp : proc.getParameters()) {
            if (pp.getType().equals(..)) {
                return true;
            }
        }
        return (proc.getResultSet() != null);
    }
    private static boolean allowedProcedure(Procedure proc) {
        // any number of in, inouts, but can have only one LOB if lob is present
        // only *one* out or inout or result, or resultset allowed
        int inouts = 0;
        int lobs = 0;
        int outs = 0;
        for (ProcedureParameter pp : proc.getParameters()) {
            if (pp.getType().equals(..) || 
                    pp.getType().equals(..)) {
                inouts++;
                if (DataTypeManager.isLOB(pp.getRuntimeType())) {
                    lobs++;
                }                
            }
            
            if (pp.getType().equals(..) || 
                    pp.getType().equals(..)) { 
                return false;
            }
            
            if (pp.getType().equals(..)) { 
                outs++;
            }                        
        }
        
        if (proc.getResultSet() != null) {
            outs++;
        }
        
        if (outs > 1) {
            return false;
        }
        
        if (inouts > 1 && lobs >= 1) {
            return false;
        }
        
        return true;
    }
    
    private static boolean isInputParameterLob(Procedure proc) {        
        for (ProcedureParameter pp : proc.getParameters()) {
            if (!pp.getType().equals(..)
                    && DataTypeManager.isLOB(pp.getRuntimeType())) {
                return true;
            }
        }
        return false;
    }
    
    private static boolean isFuntion(Procedure proc) {
        if (doesProcedureReturn(proc) && proc.getUpdateCount() == 0
                && !isInputParameterLob(proc)) {
            return true;
        }
        return false;
    }    
    static void buildFunction(String schemaNameProcedure proc,
            ArrayList<CsdlComplexTypecomplexTypesArrayList<CsdlFunctionfunctions,
            ArrayList<CsdlFunctionImportfunctionImports) {
        CsdlFunction edmFunction = new CsdlFunction();
        edmFunction.setName(proc.getName());
        edmFunction.setBound(false);
        ArrayList<CsdlParameterparams = new ArrayList<CsdlParameter>();
        for (ProcedureParameter pp : proc.getParameters()) {
            SingletonPrimitiveType odataType = ODataTypeManager.odataType(pp.getRuntimeType());            
            if (pp.getType().equals(..)) { //$NON-NLS-1$                
                edmFunction.setReturnType(new CsdlReturnType().setType(odataType.getFullQualifiedName()));
                continue;
            } 
            
            if (pp.getType().equals(..)
                    || pp.getType().equals(..)) {
                params.add(buildParameter(ppodataType));
            }           
        }
        edmFunction.setParameters(params);
        // add a complex type for return resultset.
        ColumnSet<ProcedurereturnColumns = proc.getResultSet();
        if (returnColumns != null) {
            // if return single LOB column treat it as return instead of complex, so the behavior matches 
            // to that of the REST service.
            List<Columncolumns = returnColumns.getColumns();
            if (columns.size() == 1 && DataTypeManager.isLOB(columns.get(0).getJavaType())) {
                SingletonPrimitiveType odataType = ODataTypeManager.odataType(columns.get(0).getRuntimeType());
                edmFunction.setReturnType(new CsdlReturnType().setType(odataType.getFullQualifiedName()));                
            }
            else {
                CsdlComplexType complexType = buildComplexType(procreturnColumns);
                complexTypes.add(complexType);
                FullQualifiedName odataType = new FullQualifiedName(schemaNamecomplexType.getName());
                edmFunction.setReturnType((new CsdlReturnType().setType(odataType).setCollection(true)));
            }
        }
        CsdlFunctionImport functionImport = new CsdlFunctionImport();
        functionImport.setName(proc.getName()).setFunction(new FullQualifiedName(schemaNameproc.getName()));
        functions.add(edmFunction);
        functionImports.add(functionImport);
    }
    private static CsdlParameter buildParameter(ProcedureParameter pp,
            SingletonPrimitiveType odatatype) {
        CsdlParameter param = new CsdlParameter();
        param.setName(pp.getName());
        param.setType(odatatype.getFullQualifiedName());
        if (DataTypeManager.isArrayType(pp.getRuntimeType())) {
            param.setCollection(true);
        }
        param.setNullable(pp.getNullType() == .);
        
            param.setMaxLength(pp.getLength());
        } else if (pp.getRuntimeType().equals(..)
                || pp.getRuntimeType().equals(..)
                || pp.getRuntimeType().equals(..)) {
            param.setPrecision(pp.getPrecision());
            param.setScale(pp.getScale());
        } else {
            if (pp.getDefaultValue() != null) {
                //param.setDefaultValue(pp.getDefaultValue());
            }
        }
        return param;
    }
    static void buildAction(String schemaNameProcedure procArrayList<CsdlComplexTypecomplexTypesArrayList<CsdlActionactionsArrayList<CsdlActionImportactionImports) {
        CsdlAction edmAction = new CsdlAction();
        edmAction.setName(proc.getName());
        edmAction.setBound(false);
        ArrayList<CsdlParameterparams = new ArrayList<CsdlParameter>();        
        for (ProcedureParameter pp : proc.getParameters()) {
            SingletonPrimitiveType odatatype = ODataTypeManager.odataType(pp.getRuntimeType());
            if (pp.getType().equals(..)) { //$NON-NLS-1$                
                edmAction.setReturnType(new CsdlReturnType().setType(odatatype.getFullQualifiedName()));
                continue;
            }
            if (pp.getType().equals(..)
                    || pp.getType().equals(..)) {
                params.add(buildParameter(ppodatatype));
            }
        }
        edmAction.setParameters(params);
        // add a complex type for return resultset.
        ColumnSet<ProcedurereturnColumns = proc.getResultSet();
        if (returnColumns != null) {
            // if return single LOB column treat it as return instead of complex, so the behavior matches 
            // to that of the REST service.
            List<Columncolumns = returnColumns.getColumns();
            if (columns.size() == 1 && DataTypeManager.isLOB(columns.get(0).getJavaType())) {
                SingletonPrimitiveType odataType = ODataTypeManager.odataType(columns.get(0).getRuntimeType());
                edmAction.setReturnType(new CsdlReturnType().setType(odataType.getFullQualifiedName()));                
            }
            else {            
                CsdlComplexType complexType = buildComplexType(procreturnColumns);
                complexTypes.add(complexType);
                edmAction.setReturnType((new CsdlReturnType().setType(new FullQualifiedName(schemaNamecomplexType.getName())).setCollection(true)));
            }
        }
        CsdlActionImport actionImport = new CsdlActionImport();
        actionImport.setName(proc.getName()).setAction(new FullQualifiedName(schemaNameproc.getName()));
        actions.add(edmAction);
        actionImports.add(actionImport);
    }
    private static CsdlComplexType buildComplexType(Procedure proc,
            ColumnSet<ProcedurereturnColumns) {
        CsdlComplexType complexType = new CsdlComplexType();
        String entityTypeName = proc.getName() + "_" + returnColumns.getName(); //$NON-NLS-1$
        complexType.setName(entityTypeName);
        ArrayList<CsdlPropertyprops = new ArrayList<CsdlProperty>();
        for (Column c : returnColumns.getColumns()) {
            props.add(buildProperty(c, (c.getNullType() == .)));
        }
        complexType.setProperties(props);
        return complexType;
    }
    static List<StringgetColumnNames(List<Columncolumns) {
        ArrayList<Stringnames = new ArrayList<String>();
        for (Column c : columns) {
            names.add(c.getName());
        }
        return names;
    }
    static boolean sameColumnSet(KeyRecord recordOneKeyRecord recordTwo) {
        if (recordOne == null || recordTwo == null) {
            return false;
        }
        List<ColumnsetOne = recordOne.getColumns();
        List<ColumnsetTwo = recordTwo.getColumns();
        if (setOne.size() != setTwo.size()) {
            return false;
        }
        for (int i = 0; i < setOne.size(); i++) {
            Column one = setOne.get(i);
            Column two = setTwo.get(i);
            if (!one.getName().equals(two.getName())) {
                return false;
            }
        }
        return true;
    }
New to GrepCode? Check out our FAQ X