| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.olingo.commons.core.edm; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.olingo.commons.api.edm.EdmAction; |
| import org.apache.olingo.commons.api.edm.EdmAnnotations; |
| import org.apache.olingo.commons.api.edm.EdmComplexType; |
| import org.apache.olingo.commons.api.edm.EdmEntityContainer; |
| import org.apache.olingo.commons.api.edm.EdmEntityType; |
| import org.apache.olingo.commons.api.edm.EdmEnumType; |
| import org.apache.olingo.commons.api.edm.EdmException; |
| import org.apache.olingo.commons.api.edm.EdmFunction; |
| import org.apache.olingo.commons.api.edm.EdmSchema; |
| import org.apache.olingo.commons.api.edm.EdmTerm; |
| import org.apache.olingo.commons.api.edm.EdmTypeDefinition; |
| import org.apache.olingo.commons.api.edm.FullQualifiedName; |
| import org.apache.olingo.commons.api.edm.provider.CsdlAction; |
| import org.apache.olingo.commons.api.edm.provider.CsdlAliasInfo; |
| import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation; |
| import org.apache.olingo.commons.api.edm.provider.CsdlAnnotations; |
| import org.apache.olingo.commons.api.edm.provider.CsdlComplexType; |
| import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; |
| import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer; |
| import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainerInfo; |
| import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet; |
| import org.apache.olingo.commons.api.edm.provider.CsdlEntityType; |
| import org.apache.olingo.commons.api.edm.provider.CsdlEnumType; |
| import org.apache.olingo.commons.api.edm.provider.CsdlFunction; |
| import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty; |
| import org.apache.olingo.commons.api.edm.provider.CsdlOperation; |
| import org.apache.olingo.commons.api.edm.provider.CsdlParameter; |
| import org.apache.olingo.commons.api.edm.provider.CsdlProperty; |
| import org.apache.olingo.commons.api.edm.provider.CsdlSchema; |
| import org.apache.olingo.commons.api.edm.provider.CsdlStructuralType; |
| import org.apache.olingo.commons.api.edm.provider.CsdlTerm; |
| import org.apache.olingo.commons.api.edm.provider.CsdlTypeDefinition; |
| import org.apache.olingo.commons.api.ex.ODataException; |
| |
| public class EdmProviderImpl extends AbstractEdm { |
| |
| private final CsdlEdmProvider provider; |
| private final Map<FullQualifiedName, List<CsdlAction>> actionsMap = |
| Collections.synchronizedMap(new HashMap<FullQualifiedName, List<CsdlAction>>()); |
| private final Map<FullQualifiedName, List<CsdlFunction>> functionsMap = |
| Collections.synchronizedMap(new HashMap<FullQualifiedName, List<CsdlFunction>>()); |
| private List<CsdlSchema> termSchemaDefinition = new ArrayList<CsdlSchema>(); |
| |
| private final String SLASH = "/"; |
| private final String DOT = "."; |
| |
| public EdmProviderImpl(final CsdlEdmProvider provider) { |
| this.provider = provider; |
| } |
| |
| public EdmProviderImpl(final CsdlEdmProvider provider, final List<CsdlSchema> termSchemaDefinition) { |
| this.provider = provider; |
| this.termSchemaDefinition = termSchemaDefinition; |
| populateAnnotationMap(); |
| } |
| |
| @Override |
| public EdmEntityContainer createEntityContainer(final FullQualifiedName containerName) { |
| try { |
| CsdlEntityContainerInfo entityContainerInfo = provider.getEntityContainerInfo(containerName); |
| if (entityContainerInfo != null) { |
| addEntityContainerAnnotations(provider.getEntityContainer(), entityContainerInfo.getContainerName()); |
| return new EdmEntityContainerImpl(this, provider, entityContainerInfo.getContainerName(), |
| provider.getEntityContainer()); |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| public void addEntityContainerAnnotations(CsdlEntityContainer csdlEntityContainer, FullQualifiedName containerName) { |
| String aliasName = getAliasInfo(containerName.getNamespace()); |
| List<CsdlAnnotation> annotations = getAnnotationsMap().get(containerName.getFullQualifiedNameAsString()); |
| List<CsdlAnnotation> annotationsOnAlias = getAnnotationsMap().get(aliasName + DOT + containerName.getName()); |
| addAnnotationsOnEntityContainer(csdlEntityContainer, annotations); |
| addAnnotationsOnEntityContainer(csdlEntityContainer, annotationsOnAlias); |
| } |
| |
| /** |
| * @param csdlEntityContainer |
| * @param annotations |
| */ |
| private void addAnnotationsOnEntityContainer(CsdlEntityContainer csdlEntityContainer, |
| List<CsdlAnnotation> annotations) { |
| if (null != annotations) { |
| for (CsdlAnnotation annotation : annotations) { |
| if (!compareAnnotations(csdlEntityContainer.getAnnotations(), annotation)) { |
| csdlEntityContainer.getAnnotations().add(annotation); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public EdmEnumType createEnumType(final FullQualifiedName enumName) { |
| try { |
| CsdlEnumType enumType = provider.getEnumType(enumName); |
| if (enumType != null) { |
| addEnumTypeAnnotations(enumType, enumName); |
| return new EdmEnumTypeImpl(this, enumName, enumType); |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| public void addEnumTypeAnnotations(CsdlEnumType enumType, FullQualifiedName enumName) { |
| String aliasName = getAliasInfo(enumName.getNamespace()); |
| List<CsdlAnnotation> annotations = getAnnotationsMap().get(enumName.getFullQualifiedNameAsString()); |
| List<CsdlAnnotation> annotationsOnAlias = getAnnotationsMap().get(aliasName + DOT + enumName.getName()); |
| addAnnotationsOnEnumTypes(enumType, annotations); |
| addAnnotationsOnEnumTypes(enumType, annotationsOnAlias); |
| } |
| |
| /** |
| * @param enumType |
| * @param annotations |
| */ |
| private void addAnnotationsOnEnumTypes(CsdlEnumType enumType, List<CsdlAnnotation> annotations) { |
| if (null != annotations) { |
| for (CsdlAnnotation annotation : annotations) { |
| if (!compareAnnotations(enumType.getAnnotations(), annotation)) { |
| enumType.getAnnotations().add(annotation); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public EdmTypeDefinition createTypeDefinition(final FullQualifiedName typeDefinitionName) { |
| try { |
| CsdlTypeDefinition typeDefinition = provider.getTypeDefinition(typeDefinitionName); |
| if (typeDefinition != null) { |
| addTypeDefnAnnotations(typeDefinition, typeDefinitionName); |
| return new EdmTypeDefinitionImpl(this, typeDefinitionName, typeDefinition); |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| public void addTypeDefnAnnotations(CsdlTypeDefinition typeDefinition, FullQualifiedName typeDefinitionName) { |
| String aliasName = getAliasInfo(typeDefinitionName.getNamespace()); |
| List<CsdlAnnotation> annotations = getAnnotationsMap().get(typeDefinitionName.getFullQualifiedNameAsString()); |
| List<CsdlAnnotation> annotationsOnAlias = getAnnotationsMap().get(aliasName + DOT + typeDefinitionName.getName()); |
| addAnnotationsOnTypeDefinitions(typeDefinition, annotations); |
| addAnnotationsOnTypeDefinitions(typeDefinition, annotationsOnAlias); |
| } |
| |
| /** |
| * @param typeDefinition |
| * @param annotations |
| */ |
| private void addAnnotationsOnTypeDefinitions(CsdlTypeDefinition typeDefinition, List<CsdlAnnotation> annotations) { |
| if (null != annotations) { |
| for (CsdlAnnotation annotation : annotations) { |
| if (!compareAnnotations(typeDefinition.getAnnotations(), annotation)) { |
| typeDefinition.getAnnotations().add(annotation); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public EdmEntityType createEntityType(final FullQualifiedName entityTypeName) { |
| try { |
| CsdlEntityType entityType = provider.getEntityType(entityTypeName); |
| if (entityType != null) { |
| List<CsdlAnnotation> annotations = getAnnotationsMap().get(entityTypeName.getFullQualifiedNameAsString()); |
| String aliasName = getAliasInfo(entityTypeName.getNamespace()); |
| List<CsdlAnnotation> annotationsOnAlias = getAnnotationsMap().get(aliasName + DOT + entityTypeName.getName()); |
| addAnnotationsOnStructuralType(entityType, annotations); |
| addAnnotationsOnStructuralType(entityType, annotationsOnAlias); |
| |
| if (!isEntityDerivedFromES()) { |
| addStructuralTypeAnnotations(entityType, entityTypeName, this.provider.getEntityContainer()); |
| } |
| return new EdmEntityTypeImpl(this, entityTypeName, entityType); |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| /** |
| * Add annoations to entity types and complex types |
| * @param entityType |
| * @param annotations |
| */ |
| private void addAnnotationsOnStructuralType(CsdlStructuralType structuralType, List<CsdlAnnotation> annotations) { |
| if (null != annotations && !annotations.isEmpty()) { |
| for (CsdlAnnotation annotation : annotations) { |
| if (!compareAnnotations(structuralType.getAnnotations(), annotation)) { |
| structuralType.getAnnotations().add(annotation); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Populates a map of String (annotation target) and List of CsdlAnnotations |
| * Reads both term definition schema (external schema) and |
| * provider schema (actual metadata file) |
| */ |
| private void populateAnnotationMap() { |
| for (CsdlSchema schema : termSchemaDefinition) { |
| fetchAnnotationsInMetadataAndExternalFile(schema); |
| } |
| try { |
| if (null != provider.getSchemas()) { |
| for (CsdlSchema schema : provider.getSchemas()) { |
| fetchAnnotationsInMetadataAndExternalFile(schema); |
| } |
| } |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| /** |
| * @param schema |
| */ |
| private void fetchAnnotationsInMetadataAndExternalFile(CsdlSchema schema) { |
| List<CsdlAnnotations> annotationGrps = schema.getAnnotationGroups(); |
| for (CsdlAnnotations annotationGrp : annotationGrps) { |
| if (!getAnnotationsMap().containsKey(annotationGrp.getTarget())) { |
| getAnnotationsMap().put(annotationGrp.getTarget(), annotationGrp.getAnnotations()); |
| } else { |
| List<CsdlAnnotation> annotations = getAnnotationsMap().get(annotationGrp.getTarget()); |
| List<CsdlAnnotation> newAnnotations = new ArrayList<CsdlAnnotation>(); |
| for (CsdlAnnotation annotation : annotationGrp.getAnnotations()) { |
| if (!compareAnnotations(annotations, annotation)) { |
| newAnnotations.add(annotation); |
| } |
| } |
| if (!newAnnotations.isEmpty()) { |
| getAnnotationsMap().get(annotationGrp.getTarget()).addAll(newAnnotations); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Add the annotations defined in an external file to the property/ |
| * navigation property and the entity |
| * @param structuralType |
| * @param typeName |
| * @param csdlEntityContainer |
| */ |
| public void addStructuralTypeAnnotations(CsdlStructuralType structuralType, FullQualifiedName typeName, |
| CsdlEntityContainer csdlEntityContainer) { |
| updateAnnotationsOnStructuralProperties(structuralType, typeName, csdlEntityContainer); |
| updateAnnotationsOnStructuralNavProperties(structuralType, typeName, csdlEntityContainer); |
| } |
| |
| /** |
| * Get alias name given the namespace from the alias info |
| * @param namespace |
| * @return |
| */ |
| private String getAliasInfo(String namespace) { |
| try { |
| if (null != provider.getAliasInfos()) { |
| for (CsdlAliasInfo aliasInfo : provider.getAliasInfos()) { |
| if (null != aliasInfo.getNamespace() && |
| aliasInfo.getNamespace().equalsIgnoreCase(namespace)) { |
| return aliasInfo.getAlias(); |
| } |
| } |
| } |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| return null; |
| } |
| /** Check if annotations are added on navigation properties of a structural type |
| * @param structuralType |
| * @param typeName |
| * @param csdlEntityContainer |
| * @param isNavPropAnnotationsCleared |
| * @param annotationGrp |
| */ |
| private void updateAnnotationsOnStructuralNavProperties(CsdlStructuralType structuralType, |
| FullQualifiedName typeName, CsdlEntityContainer csdlEntityContainer) { |
| List<CsdlNavigationProperty> navProperties = structuralType.getNavigationProperties(); |
| String containerName = null; |
| String schemaName = null; |
| String entitySetName = null; |
| List<CsdlEntitySet> entitySets = csdlEntityContainer != null ? |
| csdlEntityContainer.getEntitySets() : new ArrayList<CsdlEntitySet>(); |
| if (structuralType instanceof CsdlComplexType) { |
| removeAnnotationsAddedToCTNavPropFromES(structuralType, typeName, csdlEntityContainer, navProperties, entitySets); |
| } else { |
| for (CsdlEntitySet entitySet : entitySets) { |
| entitySetName = entitySet.getName(); |
| String entityTypeName = entitySet.getTypeFQN().getFullQualifiedNameAsString(); |
| if (null != entityTypeName && entityTypeName.equalsIgnoreCase(typeName.getFullQualifiedNameAsString())) { |
| containerName = csdlEntityContainer.getName(); |
| schemaName = typeName.getNamespace(); |
| break; |
| } |
| } |
| for (CsdlNavigationProperty navProperty : navProperties) { |
| List<CsdlAnnotation> annotPropDerivedFromES = getAnnotationsMap().get(schemaName + DOT + |
| containerName + SLASH + entitySetName + SLASH + navProperty.getName()); |
| removeAnnotationsOnNavPropDerivedFromEntitySet(structuralType, navProperty, annotPropDerivedFromES); |
| String aliasName = getAliasInfo(schemaName); |
| List<CsdlAnnotation> annotPropDerivedFromESOnAlias = getAnnotationsMap().get(aliasName + DOT + |
| containerName + SLASH + entitySetName + SLASH + navProperty.getName()); |
| removeAnnotationsOnNavPropDerivedFromEntitySet(structuralType, navProperty, annotPropDerivedFromESOnAlias); |
| |
| List<CsdlAnnotation> navPropAnnotations = getAnnotationsMap().get( |
| typeName + SLASH + navProperty.getName()); |
| addAnnotationsOnNavProperties(structuralType, navProperty, navPropAnnotations); |
| aliasName = getAliasInfo(typeName.getNamespace()); |
| List<CsdlAnnotation> navPropAnnotationsOnAlias = getAnnotationsMap().get( |
| aliasName + DOT + typeName.getName() + SLASH + navProperty.getName()); |
| addAnnotationsOnNavProperties(structuralType, navProperty, navPropAnnotationsOnAlias); |
| } |
| } |
| } |
| |
| /** |
| * Adds annotations to navigation properties of entity and complex types |
| * @param structuralType |
| * @param navProperty |
| * @param navPropAnnotations |
| */ |
| private void addAnnotationsOnNavProperties(CsdlStructuralType structuralType, CsdlNavigationProperty navProperty, |
| List<CsdlAnnotation> navPropAnnotations) { |
| if (null != navPropAnnotations && !navPropAnnotations.isEmpty()) { |
| for (CsdlAnnotation annotation : navPropAnnotations) { |
| if (!compareAnnotations(structuralType.getNavigationProperty( |
| navProperty.getName()).getAnnotations(), annotation)) { |
| structuralType.getNavigationProperty(navProperty.getName()).getAnnotations(). |
| add(annotation); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Removes the annotations added to properties of structural types |
| * if annotation was added before via EntitySet path |
| * @param structuralType |
| * @param navProperty |
| * @param annotPropDerivedFromES |
| */ |
| private void removeAnnotationsOnNavPropDerivedFromEntitySet(CsdlStructuralType structuralType, |
| CsdlNavigationProperty navProperty, List<CsdlAnnotation> annotPropDerivedFromES) { |
| if (null != annotPropDerivedFromES && !annotPropDerivedFromES.isEmpty()) { |
| for (CsdlAnnotation annotation : annotPropDerivedFromES) { |
| List<CsdlAnnotation> propAnnot = structuralType.getNavigationProperty( |
| navProperty.getName()).getAnnotations(); |
| if (propAnnot.contains(annotation)) { |
| propAnnot.remove(annotation); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Remove the annotations added to navigation properties |
| * of a complex type loaded via entity set path |
| * @param structuralType |
| * @param typeName |
| * @param csdlEntityContainer |
| * @param navProperties |
| * @param entitySets |
| */ |
| private void removeAnnotationsAddedToCTNavPropFromES(CsdlStructuralType structuralType, FullQualifiedName typeName, |
| CsdlEntityContainer csdlEntityContainer, List<CsdlNavigationProperty> navProperties, |
| List<CsdlEntitySet> entitySets) { |
| String containerName; |
| String schemaName; |
| String complexPropName; |
| for (CsdlEntitySet entitySet : entitySets) { |
| try { |
| CsdlEntityType entType = provider.getEntityType(entitySet.getTypeFQN()); |
| List<CsdlProperty> entTypeProperties = null != entType ? |
| entType.getProperties() : new ArrayList<>(); |
| for (CsdlProperty entTypeProperty : entTypeProperties) { |
| if (null != entTypeProperty.getType() && |
| entTypeProperty.getType().equalsIgnoreCase(typeName.getFullQualifiedNameAsString())) { |
| complexPropName = entTypeProperty.getName(); |
| containerName = csdlEntityContainer.getName(); |
| schemaName = typeName.getNamespace(); |
| for (CsdlNavigationProperty navProperty : navProperties) { |
| List<CsdlAnnotation> annotPropDerivedFromES = getAnnotationsMap().get(schemaName + DOT + |
| containerName + SLASH + entitySet.getName() + SLASH + |
| complexPropName + SLASH + navProperty.getName()); |
| removeAnnotationsOnNavPropDerivedFromEntitySet(structuralType, navProperty, annotPropDerivedFromES); |
| String aliasName = getAliasInfo(schemaName); |
| List<CsdlAnnotation> annotPropDerivedFromESOnAlias = getAnnotationsMap().get(aliasName + DOT + |
| containerName + SLASH + entitySet.getName() + SLASH + |
| complexPropName + SLASH + navProperty.getName()); |
| removeAnnotationsOnNavPropDerivedFromEntitySet(structuralType, |
| navProperty, annotPropDerivedFromESOnAlias); |
| |
| List<CsdlAnnotation> propAnnotations = getAnnotationsMap(). |
| get(typeName.getFullQualifiedNameAsString() + SLASH + navProperty.getName()); |
| addAnnotationsOnNavProperties(structuralType, navProperty, propAnnotations); |
| aliasName = getAliasInfo(typeName.getNamespace()); |
| List<CsdlAnnotation> propAnnotationsOnAlias = getAnnotationsMap(). |
| get(aliasName + DOT + typeName.getName() + SLASH + navProperty.getName()); |
| addAnnotationsOnNavProperties(structuralType, navProperty, propAnnotationsOnAlias); |
| } |
| } |
| } |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| for (CsdlNavigationProperty navProperty : structuralType.getNavigationProperties()) { |
| List<CsdlAnnotation> propAnnotations = getAnnotationsMap(). |
| get(typeName.getFullQualifiedNameAsString() + SLASH + navProperty.getName()); |
| addAnnotationsOnNavProperties(structuralType, navProperty, propAnnotations); |
| String aliasName = getAliasInfo(typeName.getNamespace()); |
| List<CsdlAnnotation> propAnnotationsOnAlias = getAnnotationsMap(). |
| get(aliasName + DOT + typeName.getName() + SLASH + navProperty.getName()); |
| addAnnotationsOnNavProperties(structuralType, navProperty, propAnnotationsOnAlias); |
| } |
| } |
| |
| /** Check if annotations are added on properties of a structural type |
| * @param structuralType |
| * @param typeName |
| * @param csdlEntityContainer |
| */ |
| private void updateAnnotationsOnStructuralProperties(CsdlStructuralType structuralType, FullQualifiedName typeName, |
| CsdlEntityContainer csdlEntityContainer) { |
| List<CsdlProperty> properties = structuralType.getProperties(); |
| String containerName = null; |
| String schemaName = null; |
| String entitySetName = null; |
| List<CsdlEntitySet> entitySets = null != csdlEntityContainer ? |
| csdlEntityContainer.getEntitySets() : new ArrayList<>(); |
| if (structuralType instanceof CsdlComplexType) { |
| removeAnnotationsAddedToCTTypePropFromES(structuralType, typeName, csdlEntityContainer, properties, entitySets); |
| } else { |
| for (CsdlEntitySet entitySet : entitySets) { |
| entitySetName = entitySet.getName(); |
| String entityTypeName = entitySet.getTypeFQN().getFullQualifiedNameAsString(); |
| if (null != entityTypeName && entityTypeName.equalsIgnoreCase(typeName.getFullQualifiedNameAsString())) { |
| containerName = csdlEntityContainer.getName(); |
| schemaName = typeName.getNamespace(); |
| break; |
| } |
| } |
| for (CsdlProperty property : properties) { |
| List<CsdlAnnotation> annotPropDerivedFromES = getAnnotationsMap().get(schemaName + DOT + |
| containerName + SLASH + entitySetName + SLASH + property.getName()); |
| removeAnnotationsOnPropDerivedFromEntitySet(structuralType, property, annotPropDerivedFromES); |
| String aliasName = getAliasInfo(schemaName); |
| List<CsdlAnnotation> annotPropDerivedFromESOnAlias = getAnnotationsMap().get(aliasName + DOT + |
| containerName + SLASH + entitySetName + SLASH + property.getName()); |
| removeAnnotationsOnPropDerivedFromEntitySet(structuralType, property, annotPropDerivedFromESOnAlias); |
| List<CsdlAnnotation> propAnnotations = getAnnotationsMap(). |
| get(typeName.getFullQualifiedNameAsString() + SLASH + property.getName()); |
| addAnnotationsOnPropertiesOfStructuralType(structuralType, property, propAnnotations); |
| aliasName = getAliasInfo(typeName.getNamespace()); |
| List<CsdlAnnotation> propAnnotationsOnAlias = getAnnotationsMap(). |
| get(aliasName + DOT + typeName.getName() + SLASH + property.getName()); |
| addAnnotationsOnPropertiesOfStructuralType(structuralType, property, propAnnotationsOnAlias); |
| } |
| } |
| } |
| |
| /** |
| * Adds annotations to properties of entity type and complex type |
| * @param structuralType |
| * @param property |
| * @param propAnnotations |
| */ |
| private void addAnnotationsOnPropertiesOfStructuralType(CsdlStructuralType structuralType, CsdlProperty property, |
| List<CsdlAnnotation> propAnnotations) { |
| if (null != propAnnotations && !propAnnotations.isEmpty()) { |
| for (CsdlAnnotation annotation : propAnnotations) { |
| if (!compareAnnotations(structuralType.getProperty( |
| property.getName()).getAnnotations(), annotation)) { |
| structuralType.getProperty(property.getName()).getAnnotations().add(annotation); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Removes the annotations added to properties of entity type when added via entity set |
| * @param structuralType |
| * @param property |
| * @param annotPropDerivedFromESOnAlias |
| */ |
| private void removeAnnotationsOnPropDerivedFromEntitySet(CsdlStructuralType structuralType, CsdlProperty property, |
| List<CsdlAnnotation> annotPropDerivedFromES) { |
| if (null != annotPropDerivedFromES && !annotPropDerivedFromES.isEmpty()) { |
| for (CsdlAnnotation annotation : annotPropDerivedFromES) { |
| List<CsdlAnnotation> propAnnot = structuralType.getProperty( |
| property.getName()).getAnnotations(); |
| if (propAnnot.contains(annotation)) { |
| propAnnot.remove(annotation); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Removes the annotation added on complex type property via Entity Set |
| * @param structuralType |
| * @param typeName |
| * @param csdlEntityContainer |
| * @param properties |
| * @param entitySets |
| */ |
| private void removeAnnotationsAddedToCTTypePropFromES(CsdlStructuralType structuralType, FullQualifiedName typeName, |
| CsdlEntityContainer csdlEntityContainer, List<CsdlProperty> properties, List<CsdlEntitySet> entitySets) { |
| String containerName; |
| String schemaName; |
| String complexPropName; |
| for (CsdlEntitySet entitySet : entitySets) { |
| try { |
| CsdlEntityType entType = provider.getEntityType(entitySet.getTypeFQN()); |
| List<CsdlProperty> entTypeProperties = null != entType ? |
| entType.getProperties() : new ArrayList<>(); |
| for (CsdlProperty entTypeProperty : entTypeProperties) { |
| if (null != entTypeProperty.getType() && |
| entTypeProperty.getType().endsWith(DOT + structuralType.getName())) { |
| complexPropName = entTypeProperty.getName(); |
| containerName = csdlEntityContainer.getName(); |
| schemaName = typeName.getNamespace(); |
| for (CsdlProperty property : properties) { |
| List<CsdlAnnotation> annotPropDerivedFromES = getAnnotationsMap().get(schemaName + DOT + |
| containerName + SLASH + entitySet.getName() + SLASH + complexPropName + SLASH + property.getName()); |
| removeAnnotationsOnPropDerivedFromEntitySet(structuralType, property, annotPropDerivedFromES); |
| String aliasName = getAliasInfo(schemaName); |
| List<CsdlAnnotation> annotPropDerivedFromESOnAlias = getAnnotationsMap().get(aliasName + DOT + |
| containerName + SLASH + entitySet.getName() + SLASH + complexPropName + SLASH + property.getName()); |
| removeAnnotationsOnPropDerivedFromEntitySet(structuralType, property, annotPropDerivedFromESOnAlias); |
| |
| List<CsdlAnnotation> propAnnotations = getAnnotationsMap(). |
| get(typeName.getFullQualifiedNameAsString() + SLASH + property.getName()); |
| addAnnotationsOnPropertiesOfStructuralType(structuralType, property, propAnnotations); |
| aliasName = getAliasInfo(typeName.getNamespace()); |
| List<CsdlAnnotation> propAnnotationsOnAlias = getAnnotationsMap(). |
| get(typeName.getName() + SLASH + property.getName()); |
| addAnnotationsOnPropertiesOfStructuralType(structuralType, property, propAnnotationsOnAlias); |
| } |
| } |
| } |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| } |
| |
| @Override |
| public EdmComplexType createComplexType(final FullQualifiedName complexTypeName) { |
| try { |
| final CsdlComplexType complexType = provider.getComplexType(complexTypeName); |
| if (complexType != null) { |
| List<CsdlAnnotation> annotations = getAnnotationsMap().get(complexTypeName.getFullQualifiedNameAsString()); |
| if (null != annotations && !annotations.isEmpty()) { |
| addAnnotationsOnStructuralType(complexType, annotations); |
| } |
| String aliasName = getAliasInfo(complexTypeName.getNamespace()); |
| List<CsdlAnnotation> annotationsOnAlias = getAnnotationsMap().get(aliasName + DOT + complexTypeName.getName()); |
| if (null != annotationsOnAlias && !annotationsOnAlias.isEmpty()) { |
| addAnnotationsOnStructuralType(complexType, annotationsOnAlias); |
| } |
| |
| if (!isComplexDerivedFromES()) { |
| addStructuralTypeAnnotations(complexType, complexTypeName, provider.getEntityContainer()); |
| } |
| return new EdmComplexTypeImpl(this, complexTypeName, complexType); |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| @Override |
| public EdmAction createBoundAction(final FullQualifiedName actionName, |
| final FullQualifiedName bindingParameterTypeName, final Boolean isBindingParameterCollection) { |
| |
| try { |
| List<CsdlAction> actions = actionsMap.get(actionName); |
| if (actions == null) { |
| actions = provider.getActions(actionName); |
| if (actions == null) { |
| return null; |
| } else { |
| actionsMap.put(actionName, actions); |
| } |
| } |
| // Search for bound action where binding parameter matches |
| for (CsdlAction action : actions) { |
| if (action.isBound()) { |
| final List<CsdlParameter> parameters = action.getParameters(); |
| final CsdlParameter parameter = parameters.get(0); |
| if ((bindingParameterTypeName.equals(parameter.getTypeFQN()) || |
| isEntityPreviousTypeCompatibleToBindingParam(bindingParameterTypeName, parameter) || |
| isComplexPreviousTypeCompatibleToBindingParam(bindingParameterTypeName, parameter, |
| isBindingParameterCollection)) |
| && isBindingParameterCollection.booleanValue() == parameter.isCollection()) { |
| addOperationsAnnotations(action, actionName); |
| return new EdmActionImpl(this, actionName, action); |
| } |
| |
| } |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| public void addOperationsAnnotations(CsdlOperation operation, FullQualifiedName actionName) { |
| String aliasName = getAliasInfo(actionName.getNamespace()); |
| List<CsdlAnnotation> annotations = getAnnotationsMap().get(actionName.getFullQualifiedNameAsString()); |
| List<CsdlAnnotation> annotationsOnAlias = getAnnotationsMap().get(aliasName + DOT + actionName.getName()); |
| if (null != annotations) { |
| addAnnotationsToOperations(operation, annotations); |
| } |
| if (null != annotationsOnAlias) { |
| addAnnotationsToOperations(operation, annotationsOnAlias); |
| } |
| addAnnotationsToParamsOfOperations(operation, actionName); |
| } |
| |
| /** Adds annotations to action parameters |
| * @param operation |
| * @param actionName |
| * @param annotations |
| */ |
| private void addAnnotationsToParamsOfOperations(CsdlOperation operation, FullQualifiedName actionName) { |
| final List<CsdlParameter> parameters = operation.getParameters(); |
| for (CsdlParameter parameter : parameters) { |
| List<CsdlAnnotation> annotsToParams = getAnnotationsMap().get( |
| actionName.getFullQualifiedNameAsString() + SLASH + parameter.getName()); |
| if (null != annotsToParams && !annotsToParams.isEmpty()) { |
| for (CsdlAnnotation annotation : annotsToParams) { |
| if (!compareAnnotations(operation.getParameter(parameter.getName()).getAnnotations(), annotation)) { |
| operation.getParameter(parameter.getName()).getAnnotations().add(annotation); |
| } |
| } |
| } |
| String aliasName = getAliasInfo(actionName.getNamespace()); |
| List<CsdlAnnotation> annotsToParamsOnAlias = getAnnotationsMap().get( |
| aliasName + DOT + actionName.getName() + SLASH + parameter.getName()); |
| if (null != annotsToParamsOnAlias && !annotsToParamsOnAlias.isEmpty()) { |
| for (CsdlAnnotation annotation : annotsToParamsOnAlias) { |
| if (!compareAnnotations(operation.getParameter(parameter.getName()).getAnnotations(), annotation)) { |
| operation.getParameter(parameter.getName()).getAnnotations().add(annotation); |
| } |
| } |
| } |
| } |
| } |
| |
| /** Adds annotations to action |
| * @param operation |
| * @param annotationsOnAlias |
| */ |
| private void addAnnotationsToOperations(CsdlOperation operation, List<CsdlAnnotation> annotations) { |
| for (CsdlAnnotation annotation : annotations) { |
| if (!compareAnnotations(operation.getAnnotations(), annotation)) { |
| operation.getAnnotations().add(annotation); |
| } |
| } |
| } |
| |
| /** |
| * @param bindingParameterTypeName |
| * @param parameter |
| * @param isBindingParameterCollection |
| * @return |
| * @throws ODataException |
| */ |
| private boolean isComplexPreviousTypeCompatibleToBindingParam( |
| final FullQualifiedName bindingParameterTypeName, final CsdlParameter parameter, |
| Boolean isBindingParameterCollection) |
| throws ODataException { |
| CsdlComplexType complexType = provider.getComplexType(bindingParameterTypeName); |
| if(provider.getEntityType(parameter.getTypeFQN()) == null){ |
| return false; |
| } |
| List<CsdlProperty> properties = provider.getEntityType(parameter.getTypeFQN()).getProperties(); |
| for (CsdlProperty property : properties) { |
| String paramPropertyTypeName = property.getTypeAsFQNObject().getFullQualifiedNameAsString(); |
| if ((complexType != null && complexType.getBaseType() != null && |
| complexType.getBaseTypeFQN().getFullQualifiedNameAsString().equals(paramPropertyTypeName)) || |
| paramPropertyTypeName.equals(bindingParameterTypeName.getFullQualifiedNameAsString()) && |
| isBindingParameterCollection.booleanValue() == property.isCollection()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * @param bindingParameterTypeName |
| * @param parameter |
| * @return |
| * @throws ODataException |
| */ |
| private boolean isEntityPreviousTypeCompatibleToBindingParam(final FullQualifiedName bindingParameterTypeName, |
| final CsdlParameter parameter) throws ODataException { |
| return provider.getEntityType(bindingParameterTypeName) != null && |
| provider.getEntityType(bindingParameterTypeName).getBaseTypeFQN() != null && |
| provider.getEntityType(bindingParameterTypeName).getBaseTypeFQN().equals(parameter.getTypeFQN()); |
| } |
| |
| @Override |
| public EdmFunction createBoundFunction(final FullQualifiedName functionName, |
| final FullQualifiedName bindingParameterTypeName, final Boolean isBindingParameterCollection, |
| final List<String> parameterNames) { |
| |
| try { |
| List<CsdlFunction> functions = functionsMap.get(functionName); |
| if (functions == null) { |
| functions = provider.getFunctions(functionName); |
| if (functions == null) { |
| return null; |
| } else { |
| functionsMap.put(functionName, functions); |
| } |
| } |
| final List<String> parameterNamesCopy = |
| parameterNames == null ? Collections.<String> emptyList() : parameterNames; |
| for (CsdlFunction function : functions) { |
| if (function.isBound()) { |
| List<CsdlParameter> providerParameters = function.getParameters(); |
| if (providerParameters == null || providerParameters.isEmpty()) { |
| throw new EdmException("No parameter specified for bound function: " + functionName); |
| } |
| final CsdlParameter bindingParameter = providerParameters.get(0); |
| if ((bindingParameterTypeName.equals(bindingParameter.getTypeFQN()) |
| ||isEntityPreviousTypeCompatibleToBindingParam(bindingParameterTypeName, bindingParameter) || |
| isComplexPreviousTypeCompatibleToBindingParam(bindingParameterTypeName, bindingParameter, |
| isBindingParameterCollection)) |
| && isBindingParameterCollection.booleanValue() == bindingParameter.isCollection() |
| && parameterNamesCopy.size() == providerParameters.size() - 1) { |
| |
| final List<String> providerParameterNames = new ArrayList<String>(); |
| for (int i = 1; i < providerParameters.size(); i++) { |
| providerParameterNames.add(providerParameters.get(i).getName()); |
| } |
| if (parameterNamesCopy.containsAll(providerParameterNames)) { |
| addOperationsAnnotations(function, functionName); |
| return new EdmFunctionImpl(this, functionName, function); |
| } |
| } |
| } |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| |
| @Override |
| protected Map<String, String> createAliasToNamespaceInfo() { |
| final Map<String, String> aliasToNamespaceInfos = new HashMap<>(); |
| try { |
| final List<CsdlAliasInfo> aliasInfos = provider.getAliasInfos(); |
| if (aliasInfos != null) { |
| for (CsdlAliasInfo info : aliasInfos) { |
| aliasToNamespaceInfos.put(info.getAlias(), info.getNamespace()); |
| } |
| } |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| return aliasToNamespaceInfos; |
| } |
| |
| @Override |
| protected EdmAction createUnboundAction(final FullQualifiedName actionName) { |
| try { |
| List<CsdlAction> actions = actionsMap.get(actionName); |
| if (actions == null) { |
| actions = provider.getActions(actionName); |
| if (actions == null) { |
| return null; |
| } else { |
| actionsMap.put(actionName, actions); |
| } |
| } |
| // Search for first unbound action |
| for (CsdlAction action : actions) { |
| if (!action.isBound()) { |
| addOperationsAnnotations(action, actionName); |
| return new EdmActionImpl(this, actionName, action); |
| } |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| @Override |
| protected List<EdmFunction> createUnboundFunctions(final FullQualifiedName functionName) { |
| List<EdmFunction> result = new ArrayList<>(); |
| |
| try { |
| List<CsdlFunction> functions = functionsMap.get(functionName); |
| if (functions == null) { |
| functions = provider.getFunctions(functionName); |
| if (functions != null) { |
| functionsMap.put(functionName, functions); |
| } |
| } |
| if (functions != null) { |
| for (CsdlFunction function : functions) { |
| if (!function.isBound()) { |
| addOperationsAnnotations(function, functionName); |
| result.add(new EdmFunctionImpl(this, functionName, function)); |
| } |
| } |
| } |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| |
| return result; |
| } |
| |
| @Override |
| protected EdmFunction createUnboundFunction(final FullQualifiedName functionName, final List<String> parameterNames) { |
| try { |
| List<CsdlFunction> functions = functionsMap.get(functionName); |
| if (functions == null) { |
| functions = provider.getFunctions(functionName); |
| if (functions == null) { |
| return null; |
| } else { |
| functionsMap.put(functionName, functions); |
| } |
| } |
| |
| final List<String> parameterNamesCopy = |
| parameterNames == null ? Collections.<String> emptyList() : parameterNames; |
| for (CsdlFunction function : functions) { |
| if (!function.isBound()) { |
| List<CsdlParameter> providerParameters = function.getParameters(); |
| if (providerParameters == null) { |
| providerParameters = Collections.emptyList(); |
| } |
| if (parameterNamesCopy.size() == providerParameters.size()) { |
| final List<String> functionParameterNames = new ArrayList<>(); |
| for (CsdlParameter parameter : providerParameters) { |
| functionParameterNames.add(parameter.getName()); |
| } |
| |
| if (parameterNamesCopy.containsAll(functionParameterNames)) { |
| addOperationsAnnotations(function, functionName); |
| addAnnotationsToParamsOfOperations(function, functionName); |
| return new EdmFunctionImpl(this, functionName, function); |
| } |
| } |
| } |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| @Override |
| protected Map<String, EdmSchema> createSchemas() { |
| try { |
| final Map<String, EdmSchema> providerSchemas = new LinkedHashMap<>(); |
| List<CsdlSchema> localSchemas = provider.getSchemas(); |
| if (localSchemas != null) { |
| for (CsdlSchema schema : localSchemas) { |
| providerSchemas.put(schema.getNamespace(), new EdmSchemaImpl(this, provider, schema)); |
| } |
| } |
| for (CsdlSchema termSchemaDefn : termSchemaDefinition) { |
| providerSchemas.put(termSchemaDefn.getNamespace(), |
| new EdmSchemaImpl(this, provider, termSchemaDefn)); |
| } |
| return providerSchemas; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| @Override |
| protected EdmTerm createTerm(final FullQualifiedName termName) { |
| try { |
| CsdlTerm providerTerm = provider.getTerm(termName); |
| if (providerTerm != null) { |
| return new EdmTermImpl(this, termName.getNamespace(), providerTerm); |
| } else { |
| for (CsdlSchema schema : termSchemaDefinition) { |
| if (schema.getNamespace().equalsIgnoreCase(termName.getNamespace()) || |
| (null != schema.getAlias() && |
| schema.getAlias().equalsIgnoreCase(termName.getNamespace()))) { |
| List<CsdlTerm> terms = schema.getTerms(); |
| for (CsdlTerm term : terms) { |
| if (term.getName().equals(termName.getName())) { |
| return new EdmTermImpl(this, termName.getNamespace(), term); |
| } |
| } |
| } |
| } |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| @Override |
| protected EdmAnnotations createAnnotationGroup(final FullQualifiedName targetName, String qualifier) { |
| try { |
| CsdlAnnotations providerGroup = provider.getAnnotationsGroup(targetName, qualifier); |
| if (null == providerGroup) { |
| for(CsdlSchema schema : termSchemaDefinition) { |
| providerGroup = schema.getAnnotationGroup(targetName.getFullQualifiedNameAsString(), qualifier); |
| break; |
| } |
| } |
| if (providerGroup != null) { |
| return new EdmAnnotationsImpl(this, providerGroup); |
| } |
| return null; |
| } catch (ODataException e) { |
| throw new EdmException(e); |
| } |
| } |
| |
| public List<CsdlSchema> getTermSchemaDefinitions() { |
| return termSchemaDefinition; |
| } |
| |
| private boolean compareAnnotations(List<CsdlAnnotation> annotations, CsdlAnnotation annotation) { |
| for (CsdlAnnotation annot : annotations) { |
| if (annot.equals(annotation)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |