blob: abd17da870628c1c1ac6bef9ec4777c906939f52 [file] [log] [blame]
/*
* 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;
}
}