[OLINGO-1180] Validation of metadata post deserialization
This commit is contained in:
parent
379a3c706e
commit
48263a8ce3
|
@ -28,6 +28,7 @@ import org.apache.olingo.client.api.communication.request.retrieve.RetrieveReque
|
|||
import org.apache.olingo.client.api.domain.ClientObjectFactory;
|
||||
import org.apache.olingo.client.api.serialization.ClientODataDeserializer;
|
||||
import org.apache.olingo.client.api.serialization.ODataBinder;
|
||||
import org.apache.olingo.client.api.serialization.ODataMetadataValidation;
|
||||
import org.apache.olingo.client.api.serialization.ODataReader;
|
||||
import org.apache.olingo.client.api.serialization.ODataSerializer;
|
||||
import org.apache.olingo.client.api.serialization.ODataWriter;
|
||||
|
@ -75,4 +76,6 @@ public interface ODataClient {
|
|||
CUDRequestFactory getCUDRequestFactory();
|
||||
|
||||
BatchRequestFactory getBatchRequestFactory();
|
||||
|
||||
ODataMetadataValidation metadataValidation();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.client.api.serialization;
|
||||
|
||||
import org.apache.olingo.client.api.edm.xml.XMLMetadata;
|
||||
import org.apache.olingo.commons.api.edm.Edm;
|
||||
|
||||
public interface ODataMetadataValidation {
|
||||
|
||||
/**
|
||||
* This method validates the metadata based on the Edm provided
|
||||
* @param edm
|
||||
*/
|
||||
void validateMetadata(Edm edm);
|
||||
|
||||
/**
|
||||
* This method validates the metadata based on the XMLMetadata provided
|
||||
* @param xmlMetadata
|
||||
*/
|
||||
void validateMetadata(XMLMetadata xmlMetadata);
|
||||
}
|
|
@ -30,6 +30,7 @@ import org.apache.olingo.client.api.communication.request.retrieve.RetrieveReque
|
|||
import org.apache.olingo.client.api.domain.ClientObjectFactory;
|
||||
import org.apache.olingo.client.api.serialization.ClientODataDeserializer;
|
||||
import org.apache.olingo.client.api.serialization.ODataBinder;
|
||||
import org.apache.olingo.client.api.serialization.ODataMetadataValidation;
|
||||
import org.apache.olingo.client.api.serialization.ODataReader;
|
||||
import org.apache.olingo.client.api.serialization.ODataSerializer;
|
||||
import org.apache.olingo.client.api.serialization.ODataWriter;
|
||||
|
@ -47,6 +48,7 @@ import org.apache.olingo.client.core.serialization.AtomSerializer;
|
|||
import org.apache.olingo.client.core.serialization.ClientODataDeserializerImpl;
|
||||
import org.apache.olingo.client.core.serialization.JsonSerializer;
|
||||
import org.apache.olingo.client.core.serialization.ODataBinderImpl;
|
||||
import org.apache.olingo.client.core.serialization.ODataMetadataValidationImpl;
|
||||
import org.apache.olingo.client.core.serialization.ODataReaderImpl;
|
||||
import org.apache.olingo.client.core.serialization.ODataWriterImpl;
|
||||
import org.apache.olingo.client.core.uri.FilterFactoryImpl;
|
||||
|
@ -80,6 +82,8 @@ public class ODataClientImpl implements ODataClient {
|
|||
protected final Configuration configuration = new ConfigurationImpl();
|
||||
|
||||
private final ODataWriter writer = new ODataWriterImpl(this);
|
||||
|
||||
private final ODataMetadataValidation metadataValidation = new ODataMetadataValidationImpl();
|
||||
|
||||
@Override
|
||||
public Configuration getConfiguration() {
|
||||
|
@ -176,4 +180,9 @@ public class ODataClientImpl implements ODataClient {
|
|||
public BatchRequestFactory getBatchRequestFactory() {
|
||||
return batchReqFact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ODataMetadataValidation metadataValidation() {
|
||||
return metadataValidation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* 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.client.core.metadatavalidator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
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.CsdlActionImport;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlComplexType;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
|
||||
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.CsdlFunction;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlFunctionImport;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlNavigationPropertyBinding;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlStructuralType;
|
||||
|
||||
public class CsdlTypeValidator {
|
||||
|
||||
private Map<String, String> aliasNamespaceMap = new HashMap<String, String>();
|
||||
private Map<FullQualifiedName, CsdlEntityContainer> csdlContainersMap =
|
||||
new HashMap<FullQualifiedName, CsdlEntityContainer>();
|
||||
private Map<FullQualifiedName, CsdlEntityType> csdlEntityTypesMap =
|
||||
new HashMap<FullQualifiedName, CsdlEntityType>();
|
||||
private Map<FullQualifiedName, CsdlComplexType> csdlComplexTypesMap =
|
||||
new HashMap<FullQualifiedName, CsdlComplexType>();
|
||||
private Map<FullQualifiedName, CsdlAction> csdlActionsMap =
|
||||
new HashMap<FullQualifiedName, CsdlAction>();
|
||||
private Map<FullQualifiedName, CsdlFunction> csdlFunctionsMap =
|
||||
new HashMap<FullQualifiedName, CsdlFunction>();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aliasNamespaceMap
|
||||
* @param csdlContainersMap
|
||||
* @param csdlEntityTypesMap
|
||||
* @param csdlComplexTypesMap
|
||||
* @param csdlActionsMap
|
||||
* @param csdlFunctionsMap
|
||||
* @param csdlTermsMap
|
||||
*/
|
||||
public CsdlTypeValidator(Map<String, String> aliasNamespaceMap,
|
||||
Map<FullQualifiedName, CsdlEntityContainer> csdlContainersMap,
|
||||
Map<FullQualifiedName, CsdlEntityType> csdlEntityTypesMap,
|
||||
Map<FullQualifiedName, CsdlComplexType> csdlComplexTypesMap,
|
||||
Map<FullQualifiedName, CsdlAction> csdlActionsMap,
|
||||
Map<FullQualifiedName, CsdlFunction> csdlFunctionsMap) {
|
||||
this.aliasNamespaceMap = aliasNamespaceMap;
|
||||
this.csdlContainersMap = csdlContainersMap;
|
||||
this.csdlEntityTypesMap = csdlEntityTypesMap;
|
||||
this.csdlComplexTypesMap = csdlComplexTypesMap;
|
||||
this.csdlActionsMap = csdlActionsMap;
|
||||
this.csdlFunctionsMap = csdlFunctionsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates metadata
|
||||
*/
|
||||
public void validateMetadataXML() {
|
||||
validateCsdlEntityTypes();
|
||||
validateCsdlComplexTypes();
|
||||
validateCsdlEntitySet();
|
||||
validateCsdlActionImport();
|
||||
validateCsdlFunctionImport();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates Csdl Entity types.
|
||||
* Looks for correct namespace aliases and correct base types
|
||||
*/
|
||||
private void validateCsdlEntityTypes() {
|
||||
for (Map.Entry<FullQualifiedName, CsdlEntityType> entityTypes : csdlEntityTypesMap.entrySet()) {
|
||||
if (entityTypes.getValue() != null && entityTypes.getKey() != null) {
|
||||
CsdlEntityType entityType = entityTypes.getValue();
|
||||
if (entityType.getBaseType() != null) {
|
||||
CsdlEntityType baseEntityType;
|
||||
FullQualifiedName baseTypeFQName = entityType.getBaseTypeFQN();
|
||||
if (!csdlEntityTypesMap.containsKey(baseTypeFQName)) {
|
||||
FullQualifiedName fqName = validateCsdlEntityTypeWithAlias(baseTypeFQName);
|
||||
baseEntityType = fetchLastCsdlBaseType(fqName);
|
||||
} else {
|
||||
baseEntityType = fetchLastCsdlBaseType(baseTypeFQName);
|
||||
}
|
||||
if (baseEntityType != null && (baseEntityType.getKey() == null ||
|
||||
baseEntityType.getKey().isEmpty())) {
|
||||
throw new RuntimeException("Missing key for EntityType " + baseEntityType.getName());
|
||||
}
|
||||
} else if (entityType.getKey() == null || entityType.getKey().isEmpty()) {
|
||||
throw new RuntimeException("Missing key for EntityType " + entityType.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This fetches the last Base Type entity from a hierarchy of base type derived types
|
||||
* @param baseTypeFQName
|
||||
* @return CsdlEntityType
|
||||
*/
|
||||
private CsdlEntityType fetchLastCsdlBaseType(FullQualifiedName baseTypeFQName) {
|
||||
CsdlEntityType baseEntityType = null;
|
||||
while (baseTypeFQName != null) {
|
||||
if (!(csdlEntityTypesMap.containsKey(baseTypeFQName))) {
|
||||
baseTypeFQName = validateCsdlEntityTypeWithAlias(baseTypeFQName);
|
||||
}
|
||||
baseEntityType = csdlEntityTypesMap.get(baseTypeFQName);
|
||||
if (baseEntityType.getKey() != null) {
|
||||
break;
|
||||
} else if (baseEntityType != null && baseEntityType.getBaseType() != null) {
|
||||
baseTypeFQName = baseEntityType.getBaseTypeFQN();
|
||||
} else if (baseEntityType.getBaseType() == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return baseEntityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* This fetches the last Base Type entity from a hierarchy of base type derived types
|
||||
* @param baseTypeFQName
|
||||
* @return CsdlNavigationProperty
|
||||
*/
|
||||
private CsdlNavigationProperty fetchLastBaseEntityHavingNavigationProperty(
|
||||
FullQualifiedName baseTypeFQName, String navBindingProperty) {
|
||||
CsdlEntityType baseEntityType = null;
|
||||
while (baseTypeFQName != null) {
|
||||
if (!(csdlEntityTypesMap.containsKey(baseTypeFQName))) {
|
||||
baseTypeFQName = validateCsdlEntityTypeWithAlias(baseTypeFQName);
|
||||
}
|
||||
baseEntityType = csdlEntityTypesMap.get(baseTypeFQName);
|
||||
if (baseEntityType.getNavigationProperty(navBindingProperty) != null) {
|
||||
break;
|
||||
} else if (baseEntityType != null && baseEntityType.getBaseType() != null) {
|
||||
baseTypeFQName = baseEntityType.getBaseTypeFQN();
|
||||
} else if (baseEntityType.getBaseType() == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (baseEntityType == null) {
|
||||
throw new RuntimeException("Entity TYpe is null with fully qualified name:" + baseTypeFQName);
|
||||
}
|
||||
return baseEntityType.getNavigationProperty(navBindingProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the namespace to alias mapping
|
||||
* @param fQName
|
||||
* @return FullQualifiedName
|
||||
*/
|
||||
private FullQualifiedName validateCsdlEntityTypeWithAlias(FullQualifiedName fQName) {
|
||||
String namespace = aliasNamespaceMap.get(fQName.getNamespace());
|
||||
FullQualifiedName fqName = new FullQualifiedName(namespace, fQName.getName());
|
||||
if (!csdlEntityTypesMap.containsKey(fqName)) {
|
||||
throw new RuntimeException("Invalid Entity Type " + fQName);
|
||||
}
|
||||
return fqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the namespace to alias mapping
|
||||
* @param fqName
|
||||
* @return FullQualifiedName
|
||||
*/
|
||||
private FullQualifiedName fetchCorrectNamespaceFromAlias(FullQualifiedName fqName) {
|
||||
if (aliasNamespaceMap.containsKey(fqName.getNamespace())) {
|
||||
String namespace = aliasNamespaceMap.get(fqName.getNamespace());
|
||||
fqName = new FullQualifiedName(namespace, fqName.getName());
|
||||
}
|
||||
return fqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates Csdl Complex types.
|
||||
* Looks for correct namespace aliases and correct complex base types
|
||||
*/
|
||||
private void validateCsdlComplexTypes() {
|
||||
for (Map.Entry<FullQualifiedName, CsdlComplexType> complexTypes : csdlComplexTypesMap.entrySet()) {
|
||||
if (complexTypes.getValue() != null && complexTypes.getKey() != null) {
|
||||
CsdlComplexType complexType = complexTypes.getValue();
|
||||
if (complexType.getBaseType() != null) {
|
||||
FullQualifiedName baseTypeFQName = complexType.getBaseTypeFQN();
|
||||
if (!csdlComplexTypesMap.containsKey(baseTypeFQName)) {
|
||||
validateCsdlComplexTypeWithAlias(baseTypeFQName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the namespace to alias mapping
|
||||
* @param aliasName
|
||||
* @return
|
||||
*/
|
||||
private FullQualifiedName validateCsdlComplexTypeWithAlias(FullQualifiedName aliasName) {
|
||||
String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
|
||||
FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
|
||||
if (!csdlComplexTypesMap.containsKey(fqName)) {
|
||||
throw new RuntimeException("Invalid Complex BaseType " + aliasName);
|
||||
}
|
||||
return fqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates Csdl entity sets.
|
||||
* It checks if entity sets are part of correct container and
|
||||
* entity types defined for entity sets are correct.
|
||||
*/
|
||||
private void validateCsdlEntitySet() {
|
||||
for (Map.Entry<FullQualifiedName, CsdlEntityContainer> container : csdlContainersMap.entrySet()) {
|
||||
for (CsdlEntitySet entitySet : container.getValue().getEntitySets()) {
|
||||
FullQualifiedName entityType = entitySet.getTypeFQN();
|
||||
if (!(csdlEntityTypesMap.containsKey(entityType))) {
|
||||
validateCsdlEntityTypeWithAlias(entityType);
|
||||
}
|
||||
validateNavigationBindingPaths(entitySet, container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks if the target entity of the navigation binding path is defined.
|
||||
* It checks if the type of navigation property of the source entity and target entity is the same
|
||||
* @param container
|
||||
* @param CsdlEntitySet
|
||||
*/
|
||||
private void validateNavigationBindingPaths(CsdlEntitySet entitySet,
|
||||
Entry<FullQualifiedName, CsdlEntityContainer> container) {
|
||||
List<CsdlNavigationPropertyBinding> navigationPropertyBindings = entitySet.getNavigationPropertyBindings();
|
||||
if (!navigationPropertyBindings.isEmpty()) {
|
||||
for (CsdlNavigationPropertyBinding navigationPropertyBinding : navigationPropertyBindings) {
|
||||
String navBindingPath = navigationPropertyBinding.getPath();
|
||||
String navBindingTarget = navigationPropertyBinding.getTarget();
|
||||
CsdlEntityType sourceEntityType = null;
|
||||
if (!(csdlEntityTypesMap.containsKey(new FullQualifiedName(entitySet.getType())))) {
|
||||
sourceEntityType = csdlEntityTypesMap.get(
|
||||
validateCsdlEntityTypeWithAlias(new FullQualifiedName(entitySet.getType())));
|
||||
} else {
|
||||
sourceEntityType = csdlEntityTypesMap.get(new FullQualifiedName(entitySet.getType()));
|
||||
}
|
||||
|
||||
CsdlNavigationProperty navProperty = null;
|
||||
String targetType = null;
|
||||
if (navBindingPath.contains("/")) {
|
||||
navProperty = findLastQualifiedNameHavingNavigationProperty(navBindingPath, sourceEntityType);
|
||||
} else {
|
||||
navProperty = (CsdlNavigationProperty) sourceEntityType.
|
||||
getNavigationProperty(navBindingPath);
|
||||
if (navProperty == null) {
|
||||
navProperty = fetchLastBaseEntityHavingNavigationProperty(
|
||||
sourceEntityType.getBaseTypeFQN(), navBindingPath);
|
||||
}
|
||||
}
|
||||
if (navBindingTarget.contains("/")) {
|
||||
targetType = findLastQualifiedTargetName(navBindingTarget);
|
||||
} else {
|
||||
if (container.getValue().getEntitySet(navBindingTarget) == null) {
|
||||
if (container.getValue().getSingleton(navBindingTarget) != null) {
|
||||
throw new RuntimeException("Validations of Singletons are not supported: "+ navBindingTarget);
|
||||
} else {
|
||||
throw new RuntimeException("Navigation Property Target " + navBindingTarget +
|
||||
" is not part of the same container " + container.getKey());
|
||||
}
|
||||
}
|
||||
FullQualifiedName fqName = container.getValue().getEntitySet(navBindingTarget).getTypeFQN();
|
||||
if (!(csdlEntityTypesMap.containsKey(fqName))) {
|
||||
fqName = validateCsdlEntityTypeWithAlias(fqName);
|
||||
}
|
||||
targetType = fqName.getFullQualifiedNameAsString();
|
||||
}
|
||||
FullQualifiedName navFQName = fetchCorrectNamespaceFromAlias(navProperty.getTypeFQN());
|
||||
validateReferentialConstraint(sourceEntityType,
|
||||
csdlEntityTypesMap.get(new FullQualifiedName(targetType)), navProperty);
|
||||
if (!(navFQName.getFullQualifiedNameAsString().equals(targetType))
|
||||
&& !(csdlEntityTypesMap.get(navFQName).getBaseTypeFQN() != null &&
|
||||
fetchCorrectNamespaceFromAlias(csdlEntityTypesMap.get(navFQName).
|
||||
getBaseTypeFQN()).getFullQualifiedNameAsString().equals(targetType))) {
|
||||
throw new RuntimeException("Navigation Property Type " +
|
||||
navFQName +" does not match "
|
||||
+ "the binding target type " + targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sourceEntityType
|
||||
* @param targetEntityType
|
||||
* @param navProperty
|
||||
*/
|
||||
private void validateReferentialConstraint(CsdlEntityType sourceEntityType, CsdlEntityType targetEntityType,
|
||||
CsdlNavigationProperty navProperty) {
|
||||
if (!navProperty.getReferentialConstraints().isEmpty()) {
|
||||
String propertyName = navProperty.getReferentialConstraints().get(0).getProperty();
|
||||
if (sourceEntityType.getProperty(propertyName) == null) {
|
||||
throw new RuntimeException("Property name " + propertyName + " not part of the source entity.");
|
||||
}
|
||||
String referencedPropertyName = navProperty.getReferentialConstraints().get(0).getReferencedProperty();
|
||||
if (targetEntityType.getProperty(referencedPropertyName) == null) {
|
||||
throw new RuntimeException("Property name " + referencedPropertyName + " not part of the target entity.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This looks for the correct entity set
|
||||
* when the target entity set is part of some other namespace
|
||||
* e.g <NavigationPropertyBinding Path="Products" Target="SomeModel.SomeContainer/SomeSet" />
|
||||
* @param navBindingTarget
|
||||
* @return String
|
||||
*/
|
||||
private String findLastQualifiedTargetName(String navBindingTarget) {
|
||||
String[] targetPaths = navBindingTarget.split("/");
|
||||
CsdlEntityContainer csdlContainer = csdlContainersMap.containsKey(new FullQualifiedName(targetPaths[0])) ?
|
||||
csdlContainersMap.get(new FullQualifiedName(targetPaths[0])) :
|
||||
csdlContainersMap.get(fetchCorrectNamespaceFromAlias(new FullQualifiedName(targetPaths[0])));
|
||||
if (csdlContainer == null) {
|
||||
throw new RuntimeException("Container with FullyQualifiedName " + targetPaths[0] + " not found.");
|
||||
}
|
||||
String targetEntitySetName = targetPaths[1];
|
||||
CsdlEntitySet csdlEntitySet = csdlContainer.getEntitySet(targetEntitySetName);
|
||||
if (csdlEntitySet == null) {
|
||||
throw new RuntimeException("Target Entity Set mentioned in navigationBindingProperty "
|
||||
+ "not found in the container " + csdlContainer.getName());
|
||||
}
|
||||
FullQualifiedName fqName = csdlEntitySet.getTypeFQN();
|
||||
if (!(csdlEntityTypesMap.containsKey(fqName))) {
|
||||
fqName = validateCsdlEntityTypeWithAlias(fqName);
|
||||
}
|
||||
return fqName.getFullQualifiedNameAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This looks for the last fully qualified identifier to fetch the navigation property
|
||||
* e.g if navigation property path is Microsoft.Exchange.Services.OData.Model.ItemAttachment/Item
|
||||
* then it fetches the entity ItemAttachment and fetches the navigation property Item
|
||||
* if navigation property path is EntityType/ComplexType/OData.Model.DerivedComplexType/Item
|
||||
* then it fetches the complex type DerivedComplexType and fetches the navigation property Item
|
||||
* @param navBindingPath
|
||||
* @return CsdlNavigationProperty
|
||||
*/
|
||||
private CsdlNavigationProperty findLastQualifiedNameHavingNavigationProperty(String navBindingPath,
|
||||
CsdlEntityType sourceEntityType) {
|
||||
String[] paths = navBindingPath.split("/");
|
||||
String lastFullQualifiedName = "";
|
||||
for (String path : paths) {
|
||||
if (path.contains(".")) {
|
||||
lastFullQualifiedName = path;
|
||||
}
|
||||
}
|
||||
String strNavProperty = paths[paths.length - 1];
|
||||
String remainingPath = navBindingPath.substring(navBindingPath.indexOf(lastFullQualifiedName)
|
||||
+ lastFullQualifiedName.length() + (lastFullQualifiedName.length() == 0 ? 0 : 1),
|
||||
navBindingPath.lastIndexOf(strNavProperty));
|
||||
if (remainingPath.length() > 0) {
|
||||
remainingPath = remainingPath.substring(0, remainingPath.length() - 1);
|
||||
}
|
||||
CsdlNavigationProperty navProperty = null;
|
||||
CsdlEntityType sourceEntityTypeHavingNavProp = lastFullQualifiedName.length() == 0 ? sourceEntityType :
|
||||
(csdlEntityTypesMap.containsKey(new FullQualifiedName(lastFullQualifiedName)) ?
|
||||
csdlEntityTypesMap.get(new FullQualifiedName(lastFullQualifiedName)) :
|
||||
csdlEntityTypesMap.get(fetchCorrectNamespaceFromAlias(new FullQualifiedName(lastFullQualifiedName))));
|
||||
if (sourceEntityTypeHavingNavProp == null) {
|
||||
CsdlComplexType sourceComplexTypeHavingNavProp =
|
||||
csdlComplexTypesMap.containsKey(new FullQualifiedName(lastFullQualifiedName)) ?
|
||||
csdlComplexTypesMap.get(new FullQualifiedName(lastFullQualifiedName)) :
|
||||
csdlComplexTypesMap.get(fetchCorrectNamespaceFromAlias(new FullQualifiedName(lastFullQualifiedName)));
|
||||
if (sourceComplexTypeHavingNavProp == null) {
|
||||
throw new RuntimeException("The fully Qualified type " + lastFullQualifiedName +
|
||||
" mentioned in navigation binding path not found ");
|
||||
}
|
||||
navProperty = remainingPath.length() > 0 ? fetchNavigationProperty(remainingPath, strNavProperty,
|
||||
sourceComplexTypeHavingNavProp) : sourceComplexTypeHavingNavProp.getNavigationProperty(strNavProperty);
|
||||
} else {
|
||||
navProperty = remainingPath.length() > 0 ? fetchNavigationProperty(remainingPath, strNavProperty,
|
||||
sourceEntityTypeHavingNavProp) : sourceEntityTypeHavingNavProp.getNavigationProperty(strNavProperty);
|
||||
}
|
||||
return navProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch the actual navigation property from the remaning path
|
||||
* @param remainingPath
|
||||
* @param strNavProperty
|
||||
* @param sourceTypeHavingNavProp
|
||||
* @return CsdlNavigationProperty
|
||||
*/
|
||||
private CsdlNavigationProperty fetchNavigationProperty(String remainingPath,
|
||||
String strNavProperty, CsdlStructuralType sourceTypeHavingNavProp) {
|
||||
String[] paths = remainingPath.split("/");
|
||||
for (String path : paths) {
|
||||
FullQualifiedName fqName = null;
|
||||
if (sourceTypeHavingNavProp instanceof CsdlComplexType) {
|
||||
fqName = ((CsdlComplexType)sourceTypeHavingNavProp).getProperty(path).getTypeAsFQNObject();
|
||||
} else if (sourceTypeHavingNavProp instanceof CsdlEntityType) {
|
||||
fqName = ((CsdlEntityType)sourceTypeHavingNavProp).getProperty(path).getTypeAsFQNObject();
|
||||
}
|
||||
if (fqName != null) {
|
||||
String namespace = aliasNamespaceMap.get(fqName.getNamespace());
|
||||
fqName = namespace != null ? new FullQualifiedName(namespace, fqName.getName()) : fqName;
|
||||
}
|
||||
|
||||
sourceTypeHavingNavProp = csdlEntityTypesMap.get(fqName) != null ?
|
||||
csdlEntityTypesMap.get(fqName) :
|
||||
csdlComplexTypesMap.get(fqName);
|
||||
}
|
||||
return sourceTypeHavingNavProp.getNavigationProperty(strNavProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates Csdl action import.
|
||||
* It checks if action imports are part of correct container and
|
||||
* actions defined for action imports are correct
|
||||
*/
|
||||
private void validateCsdlActionImport() {
|
||||
for (Map.Entry<FullQualifiedName, CsdlEntityContainer> container : csdlContainersMap.entrySet()) {
|
||||
for (CsdlActionImport actionImport : container.getValue().getActionImports()) {
|
||||
FullQualifiedName fqaction = actionImport.getActionFQN();
|
||||
if (!(csdlActionsMap.containsKey(fqaction))) {
|
||||
validateCsdlActionsWithAlias(fqaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the namespace to alias mapping
|
||||
* @param aliasName
|
||||
* @return FullQualifiedName
|
||||
*/
|
||||
private FullQualifiedName validateCsdlActionsWithAlias(FullQualifiedName aliasName) {
|
||||
String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
|
||||
FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
|
||||
if (!csdlActionsMap.containsKey(fqName)) {
|
||||
throw new RuntimeException("Invalid Action " + aliasName);
|
||||
}
|
||||
return fqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods validates csdl function imports.
|
||||
* It checks if function imports are part of correct container and
|
||||
* functions defined for function imports are correct
|
||||
*/
|
||||
private void validateCsdlFunctionImport() {
|
||||
for (Map.Entry<FullQualifiedName, CsdlEntityContainer> container : csdlContainersMap.entrySet()) {
|
||||
for (CsdlFunctionImport functionImport : container.getValue().getFunctionImports()) {
|
||||
FullQualifiedName fqaction = functionImport.getFunctionFQN();
|
||||
if (!(csdlFunctionsMap.containsKey(fqaction))) {
|
||||
validateCsdlFunctionsWithAlias(fqaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the namespace to alias mapping
|
||||
* @param aliasName
|
||||
* @return FullQualifiedName
|
||||
*/
|
||||
private FullQualifiedName validateCsdlFunctionsWithAlias(FullQualifiedName aliasName) {
|
||||
String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
|
||||
FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
|
||||
if (!csdlFunctionsMap.containsKey(fqName)) {
|
||||
throw new RuntimeException("Invalid Function " + aliasName);
|
||||
}
|
||||
return fqName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* 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.client.core.metadatavalidator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
|
||||
import org.apache.olingo.commons.api.edm.EdmComplexType;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||
import org.apache.olingo.commons.api.edm.EdmFunction;
|
||||
import org.apache.olingo.commons.api.edm.EdmFunctionImport;
|
||||
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
|
||||
import org.apache.olingo.commons.api.edm.EdmNavigationPropertyBinding;
|
||||
import org.apache.olingo.commons.api.edm.EdmSingleton;
|
||||
import org.apache.olingo.commons.api.edm.EdmStructuredType;
|
||||
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
||||
|
||||
public class EdmTypeValidator {
|
||||
|
||||
private Map<String, String> aliasNamespaceMap = new HashMap<String, String>();
|
||||
private Map<FullQualifiedName, EdmEntityContainer> edmContainersMap =
|
||||
new HashMap<FullQualifiedName, EdmEntityContainer>();
|
||||
private Map<FullQualifiedName, EdmEntityType> edmEntityTypesMap =
|
||||
new HashMap<FullQualifiedName, EdmEntityType>();
|
||||
private Map<FullQualifiedName, EdmComplexType> edmComplexTypesMap =
|
||||
new HashMap<FullQualifiedName, EdmComplexType>();
|
||||
private Map<FullQualifiedName, EdmFunction> edmFunctionsMap =
|
||||
new HashMap<FullQualifiedName, EdmFunction>();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aliasNamespaceMap
|
||||
* @param edmContainersMap
|
||||
* @param edmEntityTypesMap
|
||||
* @param edmComplexTypesMap
|
||||
* @param edmFunctionsMap
|
||||
* @param edmTermsMap
|
||||
*/
|
||||
public EdmTypeValidator(Map<String, String> aliasNamespaceMap,
|
||||
Map<FullQualifiedName, EdmEntityContainer> edmContainersMap,
|
||||
Map<FullQualifiedName, EdmEntityType> edmEntityTypesMap,
|
||||
Map<FullQualifiedName, EdmComplexType> edmComplexTypesMap,
|
||||
Map<FullQualifiedName, EdmFunction> edmFunctionsMap) {
|
||||
this.aliasNamespaceMap = aliasNamespaceMap;
|
||||
this.edmContainersMap = edmContainersMap;
|
||||
this.edmEntityTypesMap = edmEntityTypesMap;
|
||||
this.edmComplexTypesMap = edmComplexTypesMap;
|
||||
this.edmFunctionsMap = edmFunctionsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates Edm
|
||||
*/
|
||||
public void validateEdm() {
|
||||
validateEdmEntityTypes();
|
||||
validateEdmEntitySet();
|
||||
validateEdmFunctionImport();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates Edm Entity types.
|
||||
* Looks for correct namespace aliases and correct base types
|
||||
*/
|
||||
private void validateEdmEntityTypes() {
|
||||
for (Map.Entry<FullQualifiedName, EdmEntityType> entityTypes : edmEntityTypesMap.entrySet()) {
|
||||
if (entityTypes.getValue() != null && entityTypes.getKey() != null) {
|
||||
EdmEntityType entityType = entityTypes.getValue();
|
||||
if (entityType.getBaseType() != null) {
|
||||
FullQualifiedName baseTypeFQName = entityType.getBaseType().getFullQualifiedName();
|
||||
EdmEntityType baseEntityType = edmEntityTypesMap.get(baseTypeFQName);
|
||||
|
||||
if (baseEntityType != null && baseEntityType.getKeyPredicateNames().isEmpty()) {
|
||||
throw new RuntimeException("Missing key for EntityType " + baseEntityType.getName());
|
||||
}
|
||||
} else if (entityType.getKeyPredicateNames().isEmpty()) {
|
||||
throw new RuntimeException("Missing key for EntityType " + entityType.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates Edm entity sets.
|
||||
* It checks if entity sets are part of correct container and
|
||||
* entity types defined for entity sets are correct and
|
||||
* validates navigation property bindings
|
||||
*/
|
||||
private void validateEdmEntitySet() {
|
||||
for (Map.Entry<FullQualifiedName, EdmEntityContainer> container : edmContainersMap.entrySet()) {
|
||||
for (EdmEntitySet entitySet : container.getValue().getEntitySets()) {
|
||||
validateNavigationBindingPaths(entitySet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks if the target entity of the navigation binding path is defined.
|
||||
* It checks if the type of navigation property of the source entity and target entity is the same
|
||||
* @param entitySet
|
||||
* @param container
|
||||
*/
|
||||
private void validateNavigationBindingPaths(EdmEntitySet entitySet) {
|
||||
List<EdmNavigationPropertyBinding> navigationPropertyBindings = entitySet.getNavigationPropertyBindings();
|
||||
if (!navigationPropertyBindings.isEmpty()) {
|
||||
for (EdmNavigationPropertyBinding navigationPropertyBinding : navigationPropertyBindings) {
|
||||
String navBindingPath = navigationPropertyBinding.getPath();
|
||||
EdmBindingTarget edmBindingTarget = entitySet.getRelatedBindingTarget(navBindingPath);
|
||||
EdmEntityType sourceEntityType = edmEntityTypesMap.get(entitySet.getEntityType().getFullQualifiedName());
|
||||
|
||||
if (edmBindingTarget instanceof EdmSingleton) {
|
||||
throw new RuntimeException("Validations of Singletons are not supported: " + edmBindingTarget.getName());
|
||||
}
|
||||
|
||||
EdmEntityType targetEntityType = edmBindingTarget.getEntityType();
|
||||
EdmNavigationProperty navProperty = null;
|
||||
if (navBindingPath.contains("/")) {
|
||||
navProperty = findLastQualifiedNameHavingNavigationProperty(navBindingPath, sourceEntityType);
|
||||
} else {
|
||||
navProperty = (EdmNavigationProperty) sourceEntityType.getProperty(navBindingPath);
|
||||
}
|
||||
FullQualifiedName navFQName = fetchCorrectNamespaceFromAlias(navProperty.getType().getFullQualifiedName());
|
||||
validateReferentialConstraint(sourceEntityType, targetEntityType, navProperty);
|
||||
String targetType = targetEntityType.getFullQualifiedName().getFullQualifiedNameAsString();
|
||||
if (!(navFQName.getFullQualifiedNameAsString().equals(targetType))
|
||||
&& !(navProperty.getType().compatibleTo(targetEntityType))) {
|
||||
throw new RuntimeException("Navigation Property Type " +
|
||||
navProperty.getType().getFullQualifiedName() +" does not match "
|
||||
+ "the binding target type " + targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sourceEntityType
|
||||
* @param targetEntityType
|
||||
* @param navProperty
|
||||
*/
|
||||
private void validateReferentialConstraint(EdmEntityType sourceEntityType, EdmEntityType targetEntityType,
|
||||
EdmNavigationProperty navProperty) {
|
||||
if (!navProperty.getReferentialConstraints().isEmpty()) {
|
||||
String propertyName = navProperty.getReferentialConstraints().get(0).getPropertyName();
|
||||
if (sourceEntityType.getProperty(propertyName) == null) {
|
||||
throw new RuntimeException("Property name "+ propertyName + " not part of the source entity.");
|
||||
}
|
||||
String referencedPropertyName = navProperty.getReferentialConstraints().get(0).getReferencedPropertyName();
|
||||
if (targetEntityType.getProperty(referencedPropertyName) == null) {
|
||||
throw new RuntimeException("Property name " + referencedPropertyName + " not part of the target entity.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This looks for the last fully qualified identifier to fetch the navigation property
|
||||
* e.g if navigation property path is Microsoft.Exchange.Services.OData.Model.ItemAttachment/Item
|
||||
* then it fetches the entity ItemAttachment and fetches the navigation property Item
|
||||
* if navigation property path is EntityType/ComplexType/OData.Model.DerivedComplexType/Item
|
||||
* then it fetches the complex type DerivedComplexType and fetches the navigation property Item
|
||||
* @param navBindingPath
|
||||
* @param sourceEntityType
|
||||
* @return EdmNavigationProperty
|
||||
*/
|
||||
private EdmNavigationProperty findLastQualifiedNameHavingNavigationProperty(String navBindingPath,
|
||||
EdmEntityType sourceEntityType) {
|
||||
String[] paths = navBindingPath.split("/");
|
||||
String lastFullQualifiedName = "";
|
||||
for (String path : paths) {
|
||||
if (path.contains(".")) {
|
||||
lastFullQualifiedName = path;
|
||||
}
|
||||
}
|
||||
String strNavProperty = paths[paths.length - 1];
|
||||
String remainingPath = navBindingPath.substring(navBindingPath.indexOf(lastFullQualifiedName)
|
||||
+ lastFullQualifiedName.length() + (lastFullQualifiedName.length() == 0 ? 0 : 1),
|
||||
navBindingPath.lastIndexOf(strNavProperty));
|
||||
if (remainingPath.length() > 0) {
|
||||
remainingPath = remainingPath.substring(0, remainingPath.length() - 1);
|
||||
}
|
||||
EdmNavigationProperty navProperty = null;
|
||||
EdmEntityType sourceEntityTypeHavingNavProp = lastFullQualifiedName.length() == 0 ? sourceEntityType :
|
||||
(edmEntityTypesMap.containsKey(new FullQualifiedName(lastFullQualifiedName)) ?
|
||||
edmEntityTypesMap.get(new FullQualifiedName(lastFullQualifiedName)) :
|
||||
edmEntityTypesMap.get(fetchCorrectNamespaceFromAlias(new FullQualifiedName(lastFullQualifiedName))));
|
||||
if (sourceEntityTypeHavingNavProp == null) {
|
||||
EdmComplexType sourceComplexTypeHavingNavProp =
|
||||
edmComplexTypesMap.containsKey(new FullQualifiedName(lastFullQualifiedName)) ?
|
||||
edmComplexTypesMap.get(new FullQualifiedName(lastFullQualifiedName)) :
|
||||
edmComplexTypesMap.get(fetchCorrectNamespaceFromAlias(new FullQualifiedName(lastFullQualifiedName)));
|
||||
if (sourceComplexTypeHavingNavProp == null) {
|
||||
throw new RuntimeException("The fully Qualified type " + lastFullQualifiedName +
|
||||
" mentioned in navigation binding path not found ");
|
||||
}
|
||||
navProperty = remainingPath.length() > 0 ? fetchNavigationProperty(remainingPath, strNavProperty,
|
||||
sourceComplexTypeHavingNavProp) : sourceComplexTypeHavingNavProp.getNavigationProperty(strNavProperty);
|
||||
} else {
|
||||
navProperty = remainingPath.length() > 0 ? fetchNavigationProperty(remainingPath, strNavProperty,
|
||||
sourceEntityTypeHavingNavProp) : sourceEntityTypeHavingNavProp.getNavigationProperty(strNavProperty);
|
||||
}
|
||||
return navProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the correct navigation property from the remaining path
|
||||
* @param remainingPath
|
||||
* @param strNavProperty
|
||||
* @param sourceTypeHavingNavProp
|
||||
* @return EdmNavigationProperty
|
||||
*/
|
||||
private EdmNavigationProperty fetchNavigationProperty(String remainingPath,
|
||||
String strNavProperty, EdmStructuredType sourceTypeHavingNavProp) {
|
||||
String[] paths = remainingPath.split("/");
|
||||
for (String path : paths) {
|
||||
FullQualifiedName fqName = null;
|
||||
if (sourceTypeHavingNavProp instanceof EdmComplexType) {
|
||||
fqName = ((EdmComplexType)sourceTypeHavingNavProp).getProperty(path).getType().getFullQualifiedName();
|
||||
} else if (sourceTypeHavingNavProp instanceof EdmEntityType) {
|
||||
fqName = ((EdmEntityType)sourceTypeHavingNavProp).getProperty(path).getType().getFullQualifiedName();
|
||||
}
|
||||
if (fqName != null) {
|
||||
String namespace = aliasNamespaceMap.get(fqName.getNamespace());
|
||||
fqName = namespace != null ? new FullQualifiedName(namespace, fqName.getName()) : fqName;
|
||||
}
|
||||
|
||||
sourceTypeHavingNavProp = edmEntityTypesMap.containsKey(fqName) ?
|
||||
edmEntityTypesMap.get(fqName) :
|
||||
edmComplexTypesMap.get(fqName);
|
||||
}
|
||||
return sourceTypeHavingNavProp.getNavigationProperty(strNavProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the namespace to alias mapping
|
||||
* @param fQName
|
||||
* @return FullQualifiedName
|
||||
*/
|
||||
private FullQualifiedName fetchCorrectNamespaceFromAlias(FullQualifiedName fqName) {
|
||||
if (aliasNamespaceMap.containsKey(fqName.getNamespace())) {
|
||||
String namespace = aliasNamespaceMap.get(fqName.getNamespace());
|
||||
fqName = new FullQualifiedName(namespace, fqName.getName());
|
||||
}
|
||||
return fqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods validates edm function imports.
|
||||
* It checks if function imports are part of correct container and
|
||||
* functions defined for function imports are correct
|
||||
*/
|
||||
private void validateEdmFunctionImport() {
|
||||
for (Map.Entry<FullQualifiedName, EdmEntityContainer> container : edmContainersMap.entrySet()) {
|
||||
for (EdmFunctionImport functionImport : container.getValue().getFunctionImports()) {
|
||||
FullQualifiedName fqFunction = functionImport.getFunctionFqn();
|
||||
if (!(edmFunctionsMap.containsKey(fqFunction))) {
|
||||
validateEdmFunctionsWithAlias(fqFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the namespace to alias mapping
|
||||
* @param aliasName
|
||||
* @return FullQualifiedName
|
||||
*/
|
||||
private FullQualifiedName validateEdmFunctionsWithAlias(FullQualifiedName aliasName) {
|
||||
String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
|
||||
FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
|
||||
if (!edmFunctionsMap.containsKey(fqName)) {
|
||||
throw new RuntimeException("Invalid Function " + aliasName);
|
||||
}
|
||||
return fqName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.client.core.serialization;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.olingo.client.api.edm.xml.XMLMetadata;
|
||||
import org.apache.olingo.client.api.serialization.ODataMetadataValidation;
|
||||
import org.apache.olingo.client.core.metadatavalidator.CsdlTypeValidator;
|
||||
import org.apache.olingo.client.core.metadatavalidator.EdmTypeValidator;
|
||||
import org.apache.olingo.commons.api.edm.Edm;
|
||||
import org.apache.olingo.commons.api.edm.EdmAction;
|
||||
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.EdmFunction;
|
||||
import org.apache.olingo.commons.api.edm.EdmSchema;
|
||||
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.CsdlComplexType;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlEntityType;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlFunction;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlSchema;
|
||||
|
||||
public class ODataMetadataValidationImpl implements ODataMetadataValidation {
|
||||
|
||||
@Override
|
||||
public void validateMetadata(Edm edm) {
|
||||
Map<FullQualifiedName, EdmEntityType> edmEntityTypesMap = new HashMap<FullQualifiedName, EdmEntityType>();
|
||||
Map<FullQualifiedName, EdmComplexType> edmComplexTypesMap = new HashMap<FullQualifiedName, EdmComplexType>();
|
||||
Map<FullQualifiedName, EdmFunction> edmFunctionsMap = new HashMap<FullQualifiedName, EdmFunction>();
|
||||
Map<FullQualifiedName, EdmEntityContainer> edmContainersMap = new HashMap<FullQualifiedName, EdmEntityContainer>();
|
||||
Map<String, String> aliasNamespaceMap = new HashMap<String, String>();
|
||||
List<EdmSchema> edmSchemas = edm.getSchemas();
|
||||
for (EdmSchema edmSchema : edmSchemas) {
|
||||
List<EdmEntityType> edmEntityTypes = edmSchema.getEntityTypes();
|
||||
for (EdmEntityType edmEntityType : edmEntityTypes) {
|
||||
edmEntityTypesMap.put(edmEntityType.getFullQualifiedName(), edmEntityType);
|
||||
}
|
||||
List<EdmComplexType> edmComplexTypes = edmSchema.getComplexTypes();
|
||||
for (EdmComplexType edmComplexType : edmComplexTypes) {
|
||||
edmComplexTypesMap.put(edmComplexType.getFullQualifiedName(), edmComplexType);
|
||||
}
|
||||
List<EdmFunction> edmFunctions = edmSchema.getFunctions();
|
||||
for (EdmFunction edmFunction : edmFunctions) {
|
||||
edmFunctionsMap.put(edmFunction.getFullQualifiedName(), edmFunction);
|
||||
}
|
||||
aliasNamespaceMap.put(edmSchema.getAlias(), edmSchema.getNamespace());
|
||||
if (edmSchema.getEntityContainer() != null) {
|
||||
edmContainersMap.put(edmSchema.getEntityContainer().getFullQualifiedName(), edmSchema.getEntityContainer());
|
||||
}
|
||||
}
|
||||
EdmTypeValidator edmTypeValidator = new EdmTypeValidator(aliasNamespaceMap, edmContainersMap,
|
||||
edmEntityTypesMap, edmComplexTypesMap, edmFunctionsMap);
|
||||
edmTypeValidator.validateEdm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateMetadata(XMLMetadata xmlMetadata) {
|
||||
Map<FullQualifiedName, CsdlEntityType> csdlEntityTypesMap = new HashMap<FullQualifiedName, CsdlEntityType>();
|
||||
Map<FullQualifiedName, CsdlComplexType> csdlComplexTypesMap = new HashMap<FullQualifiedName, CsdlComplexType>();
|
||||
Map<FullQualifiedName, CsdlAction> csdlActionsMap = new HashMap<FullQualifiedName, CsdlAction>();
|
||||
Map<FullQualifiedName, CsdlFunction> csdlFunctionsMap = new HashMap<FullQualifiedName, CsdlFunction>();
|
||||
Map<FullQualifiedName, CsdlEntityContainer> csdlContainersMap =
|
||||
new HashMap<FullQualifiedName, CsdlEntityContainer>();
|
||||
Map<String, String> aliasNamespaceMap = new HashMap<String, String>();
|
||||
List<CsdlSchema> csdlSchemas = xmlMetadata.getSchemas();
|
||||
for (CsdlSchema csdlSchema : csdlSchemas) {
|
||||
List<CsdlEntityType> csdlEntityTypes = csdlSchema.getEntityTypes();
|
||||
for (CsdlEntityType csdlEntityType : csdlEntityTypes) {
|
||||
csdlEntityTypesMap.put(new FullQualifiedName(
|
||||
csdlSchema.getNamespace(), csdlEntityType.getName()), csdlEntityType);
|
||||
}
|
||||
List<CsdlComplexType> csdlComplexTypes = csdlSchema.getComplexTypes();
|
||||
for (CsdlComplexType csdlComplexType : csdlComplexTypes) {
|
||||
csdlComplexTypesMap.put(new FullQualifiedName(
|
||||
csdlSchema.getNamespace(), csdlComplexType.getName()), csdlComplexType);
|
||||
}
|
||||
List<CsdlAction> csdlActions = csdlSchema.getActions();
|
||||
for (CsdlAction csdlAction : csdlActions) {
|
||||
csdlActionsMap.put(new FullQualifiedName(
|
||||
csdlSchema.getNamespace(), csdlAction.getName()), csdlAction);
|
||||
}
|
||||
List<CsdlFunction> csdlFunctions = csdlSchema.getFunctions();
|
||||
for (CsdlFunction csdlFunction : csdlFunctions) {
|
||||
csdlFunctionsMap.put(
|
||||
new FullQualifiedName(csdlSchema.getNamespace(), csdlFunction.getName()), csdlFunction);
|
||||
}
|
||||
aliasNamespaceMap.put(csdlSchema.getAlias(), csdlSchema.getNamespace());
|
||||
if (csdlSchema.getEntityContainer() != null) {
|
||||
csdlContainersMap.put(new FullQualifiedName(
|
||||
csdlSchema.getNamespace(), csdlSchema.getEntityContainer().getName()), csdlSchema.getEntityContainer());
|
||||
}
|
||||
}
|
||||
CsdlTypeValidator csdlTypeValidator = new CsdlTypeValidator(aliasNamespaceMap, csdlContainersMap,
|
||||
csdlEntityTypesMap, csdlComplexTypesMap, csdlActionsMap, csdlFunctionsMap);
|
||||
csdlTypeValidator.validateMetadataXML();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
|
||||
<edmx:DataServices m:DataServiceVersion="4.0" m:MaxDataServiceVersion="4.0" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata">
|
||||
<Schema Namespace="Microsoft.Exchange.Services.OData.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm">
|
||||
<EntityType Name="Customer" Abstract="true">
|
||||
<Key>
|
||||
<PropertyRef Name="CustomerId" />
|
||||
</Key>
|
||||
<Property Name="CustomerId" Type="Edm.String" Nullable="false"/>
|
||||
<Property Name="CustomerName" Type="Edm.String" />
|
||||
<Property Name="Pet" Type="Microsoft.Exchange.Services.OData.Model.Animal" />
|
||||
</EntityType>
|
||||
<EntityType Name="VipCustomer" BaseType="Microsoft.Exchange.Services.OData.Model.Customer" Abstract="true">
|
||||
<Property Name="CustomerType" Type="Edm.String" />
|
||||
<Property Name="VipLocations" Type="Collection(Microsoft.Exchange.Services.OData.Model.Address)" />
|
||||
</EntityType>
|
||||
<EntityType Name="City">
|
||||
<Key>
|
||||
<PropertyRef Name="Id" />
|
||||
</Key>
|
||||
<Property Name="Id" Type="Edm.String" Nullable="false"/>
|
||||
</EntityType>
|
||||
<ComplexType Name="Animal">
|
||||
</ComplexType>
|
||||
<ComplexType Name="Human" BaseType="Microsoft.Exchange.Services.OData.Model.Animal">
|
||||
<Property Name="HumanAddress" Type="Microsoft.Exchange.Services.OData.Model.USAddress" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="Horse" BaseType="Microsoft.Exchange.Services.OData.Model.Animal">
|
||||
<Property Name="HorseAddress" Type="Microsoft.Exchange.Services.OData.Model.USAddress" />
|
||||
<Property Name="HorseAddresses" Type="Collection(Microsoft.Exchange.Services.OData.Model.USAddress)" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="Address">
|
||||
<NavigationProperty Name="City" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="USAddress" BaseType="Microsoft.Exchange.Services.OData.Model.Address">
|
||||
<Property Name="CountryAddress" Type="Microsoft.Exchange.Services.OData.Model.CountryAddress" />
|
||||
<NavigationProperty Name="SubCity" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="CountryAddress" BaseType="Microsoft.Exchange.Services.OData.Model.Address">
|
||||
<NavigationProperty Name="SubCity" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<EntityContainer Name="EntityContainer" m:IsDefaultEntityContainer="true">
|
||||
<EntitySet Name="Customers" EntityType="Microsoft.Exchange.Services.OData.Model.Customer">
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Human/HumanAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddress/SubCity" Target="HorseCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddresses/SubCity" Target="HorseCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/CountryAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/City" Target="HumanCities" />
|
||||
</EntitySet>
|
||||
<EntitySet Name="HumanCities" EntityType="Microsoft.Exchange.Services.OData.Model.City"/>
|
||||
<EntitySet Name="HorseCities" EntityType="Microsoft.Exchange.Services.OData.Model.City"/>
|
||||
</EntityContainer>
|
||||
</Schema>
|
||||
</edmx:DataServices>
|
||||
</edmx:Edmx>
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
|
||||
<edmx:DataServices m:DataServiceVersion="4.0" m:MaxDataServiceVersion="4.0" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata">
|
||||
<Schema Namespace="Microsoft.Exchange.Services.OData.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="Namespace1_Alias">
|
||||
<EntityType Name="Customer" Abstract="true">
|
||||
<Key>
|
||||
<PropertyRef Name="CustomerId" />
|
||||
</Key>
|
||||
<Property Name="CustomerId" Type="Edm.String" Nullable="false"/>
|
||||
<Property Name="CustomerName" Type="Edm.String" />
|
||||
<Property Name="Pet" Type="Microsoft.Exchange.Services.OData.Model.Animal" />
|
||||
</EntityType>
|
||||
<EntityType Name="VipCustomer" BaseType="Microsoft.Exchange.Services.OData.Model.Customer" Abstract="true">
|
||||
<Property Name="CustomerType" Type="Edm.String" />
|
||||
<Property Name="VipLocations" Type="Collection(Microsoft.Exchange.Services.OData.Model.Address)" />
|
||||
</EntityType>
|
||||
<EntityType Name="City">
|
||||
<Key>
|
||||
<PropertyRef Name="Id" />
|
||||
</Key>
|
||||
<Property Name="Id" Type="Edm.String" Nullable="false"/>
|
||||
</EntityType>
|
||||
<ComplexType Name="Animal">
|
||||
</ComplexType>
|
||||
<ComplexType Name="Human" BaseType="Microsoft.Exchange.Services.OData.Model.Animal">
|
||||
<Property Name="HumanAddress" Type="Microsoft.Exchange.Services.OData.Model.USAddress" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="Horse" BaseType="Microsoft.Exchange.Services.OData.Model.Animal">
|
||||
<Property Name="HorseAddress" Type="Microsoft.Exchange.Services.OData.Model.USAddress" />
|
||||
<Property Name="HorseAddresses" Type="Collection(Microsoft.Exchange.Services.OData.Model.USAddress)" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="Address">
|
||||
<NavigationProperty Name="City" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="USAddress" BaseType="Microsoft.Exchange.Services.OData.Model.Address">
|
||||
<Property Name="CountryAddress" Type="Microsoft.Exchange.Services.OData.Model.CountryAddress" />
|
||||
<NavigationProperty Name="SubCity" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="CountryAddress" BaseType="Microsoft.Exchange.Services.OData.Model.Address">
|
||||
<NavigationProperty Name="SubCity" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<EntityContainer Name="EntityContainer" m:IsDefaultEntityContainer="true">
|
||||
<EntitySet Name="Customers" EntityType="Microsoft.Exchange.Services.OData.Model.Customer">
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Human/HumanAddress/SubCity" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddress/SubCity" Target="HorseCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddresses/SubCity" Target="HorseCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/SubCity" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/CountryAddress/SubCity" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/City" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
</EntitySet>
|
||||
<EntitySet Name="HorseCities" EntityType="Microsoft.Exchange.Services.OData.Model.City"/>
|
||||
</EntityContainer>
|
||||
</Schema>
|
||||
<Schema Namespace="ODataWebExperimental.OData.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm">
|
||||
<EntityContainer Name="EntityContainer1" p4:LazyLoadingEnabled="true" xmlns:p4="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
|
||||
<EntitySet Name="HumanCities" EntityType="Microsoft.Exchange.Services.OData.Model.City"/>
|
||||
<EntitySet Name="Customers" EntityType="Microsoft.Exchange.Services.OData.Model.Customer">
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Human/HumanAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddress/SubCity" Target="Namespace1_Alias.EntityContainer/HorseCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddresses/SubCity" Target="Microsoft.Exchange.Services.OData.Model.EntityContainer/HorseCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/CountryAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/City" Target="HumanCities" />
|
||||
</EntitySet>
|
||||
</EntityContainer>
|
||||
</Schema>
|
||||
</edmx:DataServices>
|
||||
</edmx:Edmx>
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
|
||||
<edmx:DataServices m:DataServiceVersion="4.0" m:MaxDataServiceVersion="4.0" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata">
|
||||
<Schema Namespace="Microsoft.Exchange.Services.OData.Model" Alias="Namespace1_Alias" xmlns="http://docs.oasis-open.org/odata/ns/edm">
|
||||
<EntityType Name="Customer" Abstract="true">
|
||||
<Key>
|
||||
<PropertyRef Name="CustomerId" />
|
||||
</Key>
|
||||
<Property Name="CustomerId" Type="Edm.String" Nullable="false"/>
|
||||
<Property Name="CustomerName" Type="Edm.String" />
|
||||
<Property Name="Pet" Type="Microsoft.Exchange.Services.OData.Model.Animal" />
|
||||
</EntityType>
|
||||
<EntityType Name="VipCustomer" BaseType="Namespace1_Alias.Customer" Abstract="true">
|
||||
<Property Name="CustomerType" Type="Edm.String" />
|
||||
<Property Name="VipLocations" Type="Collection(Namespace1_Alias.Address)" />
|
||||
</EntityType>
|
||||
<EntityType Name="City">
|
||||
<Key>
|
||||
<PropertyRef Name="Id" />
|
||||
</Key>
|
||||
<Property Name="Id" Type="Edm.String" Nullable="false"/>
|
||||
</EntityType>
|
||||
<ComplexType Name="Animal">
|
||||
</ComplexType>
|
||||
<ComplexType Name="Human" BaseType="Namespace1_Alias.Animal">
|
||||
<Property Name="HumanAddress" Type="Microsoft.Exchange.Services.OData.Model.USAddress" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="Horse" BaseType="Microsoft.Exchange.Services.OData.Model.Animal">
|
||||
<Property Name="HorseAddress" Type="Namespace1_Alias.USAddress" />
|
||||
<Property Name="HorseAddresses" Type="Collection(Microsoft.Exchange.Services.OData.Model.USAddress)" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="Address">
|
||||
<NavigationProperty Name="City" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="USAddress" BaseType="Microsoft.Exchange.Services.OData.Model.Address">
|
||||
<Property Name="CountryAddress" Type="Microsoft.Exchange.Services.OData.Model.CountryAddress" />
|
||||
<NavigationProperty Name="SubCity" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="CountryAddress" BaseType="Microsoft.Exchange.Services.OData.Model.Address">
|
||||
<NavigationProperty Name="SubCity" Type="Microsoft.Exchange.Services.OData.Model.City" />
|
||||
</ComplexType>
|
||||
<EntityContainer Name="EntityContainer" m:IsDefaultEntityContainer="true">
|
||||
<EntitySet Name="Customers" EntityType="Namespace1_Alias.Customer">
|
||||
<NavigationPropertyBinding Path="Pet/Namespace1_Alias.Human/HumanAddress/SubCity" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddress/SubCity" Target="HorseCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddresses/SubCity" Target="HorseCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/SubCity" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
<NavigationPropertyBinding Path="Namespace1_Alias.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/CountryAddress/SubCity" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/City" Target="ODataWebExperimental.OData.Model.EntityContainer1/HumanCities" />
|
||||
</EntitySet>
|
||||
<EntitySet Name="HorseCities" EntityType="Microsoft.Exchange.Services.OData.Model.City"/>
|
||||
</EntityContainer>
|
||||
</Schema>
|
||||
<Schema Namespace="ODataWebExperimental.OData.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="Namespace2_Alias">
|
||||
<EntityContainer Name="EntityContainer1" p4:LazyLoadingEnabled="true" xmlns:p4="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
|
||||
<EntitySet Name="HumanCities" EntityType="Namespace1_Alias.City"/>
|
||||
<EntitySet Name="Customers" EntityType="Microsoft.Exchange.Services.OData.Model.Customer">
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Human/HumanAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddress/SubCity" Target="Namespace1_Alias.EntityContainer/HorseCities" />
|
||||
<NavigationPropertyBinding Path="Pet/Microsoft.Exchange.Services.OData.Model.Horse/HorseAddresses/SubCity" Target="Microsoft.Exchange.Services.OData.Model.EntityContainer/HorseCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/Microsoft.Exchange.Services.OData.Model.USAddress/CountryAddress/SubCity" Target="HumanCities" />
|
||||
<NavigationPropertyBinding Path="Microsoft.Exchange.Services.OData.Model.VipCustomer/VipLocations/City" Target="HumanCities" />
|
||||
</EntitySet>
|
||||
</EntityContainer>
|
||||
</Schema>
|
||||
</edmx:DataServices>
|
||||
</edmx:Edmx>
|
|
@ -0,0 +1,355 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
|
||||
<edmx:DataServices>
|
||||
<Schema Namespace="Microsoft.OData.SampleService.Models.TripPin" xmlns="http://docs.oasis-open.org/odata/ns/edm">
|
||||
<EnumType Name="PersonGender">
|
||||
<Member Name="Male" Value="0" />
|
||||
<Member Name="Female" Value="1" />
|
||||
<Member Name="Unknown" Value="2" />
|
||||
</EnumType>
|
||||
<ComplexType Name="City">
|
||||
<Property Name="CountryRegion" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="Name" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="Region" Type="Edm.String" Nullable="false" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="Location" OpenType="true">
|
||||
<Property Name="Address" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="City" Type="Microsoft.OData.SampleService.Models.TripPin.City" Nullable="false" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="EventLocation" BaseType="Microsoft.OData.SampleService.Models.TripPin.Location" OpenType="true">
|
||||
<Property Name="BuildingInfo" Type="Edm.String" />
|
||||
</ComplexType>
|
||||
<ComplexType Name="AirportLocation" BaseType="Microsoft.OData.SampleService.Models.TripPin.Location" OpenType="true">
|
||||
<Property Name="Loc" Type="Edm.GeographyPoint" Nullable="false" SRID="4326" />
|
||||
</ComplexType>
|
||||
<EntityType Name="Photo" HasStream="true">
|
||||
<Key>
|
||||
<PropertyRef Name="Id" />
|
||||
</Key>
|
||||
<Property Name="Id" Type="Edm.Int64" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Permissions">
|
||||
<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
|
||||
</Annotation>
|
||||
</Property>
|
||||
<Property Name="Name" Type="Edm.String" />
|
||||
<Annotation Term="Org.OData.Core.V1.AcceptableMediaTypes">
|
||||
<Collection>
|
||||
<String>image/jpeg</String>
|
||||
</Collection>
|
||||
</Annotation>
|
||||
</EntityType>
|
||||
<EntityType Name="Person" OpenType="true">
|
||||
<Key>
|
||||
<PropertyRef Name="UserName" />
|
||||
</Key>
|
||||
<Property Name="UserName" Type="Edm.String" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Permissions">
|
||||
<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
|
||||
</Annotation>
|
||||
</Property>
|
||||
<Property Name="FirstName" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="LastName" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="Emails" Type="Collection(Edm.String)" />
|
||||
<Property Name="AddressInfo" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Location)" />
|
||||
<Property Name="Gender" Type="Microsoft.OData.SampleService.Models.TripPin.PersonGender" />
|
||||
<Property Name="Concurrency" Type="Edm.Int64" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Computed" Bool="true" />
|
||||
</Property>
|
||||
<NavigationProperty Name="Friends" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Person)" />
|
||||
<NavigationProperty Name="Trips" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Trip)" ContainsTarget="true" />
|
||||
<NavigationProperty Name="Photo" Type="Microsoft.OData.SampleService.Models.TripPin.Photo" />
|
||||
</EntityType>
|
||||
<EntityType Name="Airline">
|
||||
<Key>
|
||||
<PropertyRef Name="AirlineCode" />
|
||||
</Key>
|
||||
<Property Name="AirlineCode" Type="Edm.String" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Permissions">
|
||||
<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
|
||||
</Annotation>
|
||||
</Property>
|
||||
<Property Name="Name" Type="Edm.String" Nullable="false" />
|
||||
</EntityType>
|
||||
<EntityType Name="Airport">
|
||||
<Key>
|
||||
<PropertyRef Name="IcaoCode" />
|
||||
</Key>
|
||||
<Property Name="IcaoCode" Type="Edm.String" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Permissions">
|
||||
<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
|
||||
</Annotation>
|
||||
</Property>
|
||||
<Property Name="Name" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="IataCode" Type="Edm.String" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Immutable" Bool="true" />
|
||||
</Property>
|
||||
<Property Name="Location" Type="Microsoft.OData.SampleService.Models.TripPin.AirportLocation" Nullable="false" />
|
||||
</EntityType>
|
||||
<EntityType Name="PlanItem">
|
||||
<Key>
|
||||
<PropertyRef Name="PlanItemId" />
|
||||
</Key>
|
||||
<Property Name="PlanItemId" Type="Edm.Int32" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Permissions">
|
||||
<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
|
||||
</Annotation>
|
||||
</Property>
|
||||
<Property Name="ConfirmationCode" Type="Edm.String" />
|
||||
<Property Name="StartsAt" Type="Edm.DateTimeOffset" />
|
||||
<Property Name="EndsAt" Type="Edm.DateTimeOffset" />
|
||||
<Property Name="Duration" Type="Edm.Duration" />
|
||||
</EntityType>
|
||||
<EntityType Name="PublicTransportation" BaseType="Microsoft.OData.SampleService.Models.TripPin.PlanItem">
|
||||
<Property Name="SeatNumber" Type="Edm.String" />
|
||||
</EntityType>
|
||||
<EntityType Name="Flight" BaseType="Microsoft.OData.SampleService.Models.TripPin.PublicTransportation">
|
||||
<Property Name="FlightNumber" Type="Edm.String" Nullable="false" />
|
||||
<NavigationProperty Name="From" Type="Microsoft.OData.SampleService.Models.TripPin.Airport" Nullable="false" />
|
||||
<NavigationProperty Name="To" Type="Microsoft.OData.SampleService.Models.TripPin.Airport" Nullable="false" />
|
||||
<NavigationProperty Name="Airline" Type="Microsoft.OData.SampleService.Models.TripPin.Airline" Nullable="false" />
|
||||
</EntityType>
|
||||
<EntityType Name="Event" BaseType="Microsoft.OData.SampleService.Models.TripPin.PlanItem" OpenType="true">
|
||||
<Property Name="Description" Type="Edm.String" />
|
||||
<Property Name="OccursAt" Type="Microsoft.OData.SampleService.Models.TripPin.EventLocation" Nullable="false" />
|
||||
</EntityType>
|
||||
<EntityType Name="Trip">
|
||||
<Key>
|
||||
<PropertyRef Name="TripId" />
|
||||
</Key>
|
||||
<Property Name="TripId" Type="Edm.Int32" Nullable="false">
|
||||
<Annotation Term="Org.OData.Core.V1.Permissions">
|
||||
<EnumMember>Org.OData.Core.V1.Permission/Read</EnumMember>
|
||||
</Annotation>
|
||||
</Property>
|
||||
<Property Name="ShareId" Type="Edm.Guid" />
|
||||
<Property Name="Description" Type="Edm.String" />
|
||||
<Property Name="Name" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="Budget" Type="Edm.Single" Nullable="false">
|
||||
<Annotation Term="Org.OData.Measures.V1.ISOCurrency" String="USD" />
|
||||
<Annotation Term="Org.OData.Measures.V1.Scale" Int="2" />
|
||||
</Property>
|
||||
<Property Name="StartsAt" Type="Edm.DateTimeOffset" Nullable="false" />
|
||||
<Property Name="EndsAt" Type="Edm.DateTimeOffset" Nullable="false" />
|
||||
<Property Name="Tags" Type="Collection(Edm.String)" Nullable="false" />
|
||||
<NavigationProperty Name="Photos" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Photo)" />
|
||||
<NavigationProperty Name="PlanItems" Type="Collection(Microsoft.OData.SampleService.Models.TripPin.PlanItem)" ContainsTarget="true" />
|
||||
</EntityType>
|
||||
<Function Name="GetFavoriteAirline" IsBound="true" EntitySetPath="person/Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/Airline" IsComposable="true">
|
||||
<Parameter Name="person" Type="Microsoft.OData.SampleService.Models.TripPin.Person" Nullable="false" />
|
||||
<ReturnType Type="Microsoft.OData.SampleService.Models.TripPin.Airline" Nullable="false" />
|
||||
</Function>
|
||||
<Function Name="GetInvolvedPeople" IsBound="true" IsComposable="true">
|
||||
<Parameter Name="trip" Type="Microsoft.OData.SampleService.Models.TripPin.Trip" Nullable="false" />
|
||||
<ReturnType Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Person)" Nullable="false" />
|
||||
</Function>
|
||||
<Function Name="GetFriendsTrips" IsBound="true" EntitySetPath="person/Friends/Trips" IsComposable="true">
|
||||
<Parameter Name="person" Type="Microsoft.OData.SampleService.Models.TripPin.Person" Nullable="false" />
|
||||
<Parameter Name="userName" Type="Edm.String" Nullable="false" />
|
||||
<ReturnType Type="Collection(Microsoft.OData.SampleService.Models.TripPin.Trip)" Nullable="false" />
|
||||
</Function>
|
||||
<Function Name="GetNearestAirport" IsComposable="true">
|
||||
<Parameter Name="lat" Type="Edm.Double" Nullable="false" />
|
||||
<Parameter Name="lon" Type="Edm.Double" Nullable="false" />
|
||||
<ReturnType Type="Microsoft.OData.SampleService.Models.TripPin.Airport" Nullable="false" />
|
||||
</Function>
|
||||
<Action Name="ResetDataSource" />
|
||||
<Action Name="ShareTrip" IsBound="true">
|
||||
<Parameter Name="person" Type="Microsoft.OData.SampleService.Models.TripPin.Person" Nullable="false" />
|
||||
<Parameter Name="userName" Type="Edm.String" Nullable="false" />
|
||||
<Parameter Name="tripId" Type="Edm.Int32" Nullable="false" />
|
||||
</Action>
|
||||
<EntityContainer Name="DefaultContainer">
|
||||
<EntitySet Name="Photos" EntityType="Microsoft.OData.SampleService.Models.TripPin.Photo">
|
||||
<Annotation Term="Org.OData.Core.V1.ResourcePath" String="Photos" />
|
||||
<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Searchable" Bool="true" />
|
||||
<PropertyValue Property="UnsupportedExpressions">
|
||||
<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Insertable" Bool="true" />
|
||||
<PropertyValue Property="NonInsertableNavigationProperties">
|
||||
<Collection />
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
</EntitySet>
|
||||
<EntitySet Name="People" EntityType="Microsoft.OData.SampleService.Models.TripPin.Person">
|
||||
<NavigationPropertyBinding Path="Friends" Target="People" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/Airline" Target="Airlines" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/From" Target="Airports" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/To" Target="Airports" />
|
||||
<NavigationPropertyBinding Path="Photo" Target="Photos" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Trip/Photos" Target="Photos" />
|
||||
<Annotation Term="Org.OData.Core.V1.OptimisticConcurrency">
|
||||
<Collection>
|
||||
<PropertyPath>Concurrency</PropertyPath>
|
||||
</Collection>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Core.V1.ResourcePath" String="People" />
|
||||
<Annotation Term="Org.OData.Capabilities.V1.NavigationRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Navigability">
|
||||
<EnumMember>Org.OData.Capabilities.V1.NavigationType/None</EnumMember>
|
||||
</PropertyValue>
|
||||
<PropertyValue Property="RestrictedProperties">
|
||||
<Collection>
|
||||
<Record>
|
||||
<PropertyValue Property="NavigationProperty" NavigationPropertyPath="Friends" />
|
||||
<PropertyValue Property="Navigability">
|
||||
<EnumMember>Org.OData.Capabilities.V1.NavigationType/Recursive</EnumMember>
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Collection>
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Searchable" Bool="true" />
|
||||
<PropertyValue Property="UnsupportedExpressions">
|
||||
<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Insertable" Bool="true" />
|
||||
<PropertyValue Property="NonInsertableNavigationProperties">
|
||||
<Collection>
|
||||
<NavigationPropertyPath>Trips</NavigationPropertyPath>
|
||||
<NavigationPropertyPath>Friends</NavigationPropertyPath>
|
||||
</Collection>
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
</EntitySet>
|
||||
<EntitySet Name="Airlines" EntityType="Microsoft.OData.SampleService.Models.TripPin.Airline">
|
||||
<Annotation Term="Org.OData.Core.V1.ResourcePath" String="Airlines" />
|
||||
<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Searchable" Bool="true" />
|
||||
<PropertyValue Property="UnsupportedExpressions">
|
||||
<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Insertable" Bool="true" />
|
||||
<PropertyValue Property="NonInsertableNavigationProperties">
|
||||
<Collection />
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
</EntitySet>
|
||||
<EntitySet Name="Airports" EntityType="Microsoft.OData.SampleService.Models.TripPin.Airport">
|
||||
<Annotation Term="Org.OData.Core.V1.ResourcePath" String="Airports" />
|
||||
<Annotation Term="Org.OData.Capabilities.V1.SearchRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Searchable" Bool="true" />
|
||||
<PropertyValue Property="UnsupportedExpressions">
|
||||
<EnumMember>Org.OData.Capabilities.V1.SearchExpressions/none</EnumMember>
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.InsertRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Insertable" Bool="false" />
|
||||
<PropertyValue Property="NonInsertableNavigationProperties">
|
||||
<Collection />
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.DeleteRestrictions">
|
||||
<Record>
|
||||
<PropertyValue Property="Deletable" Bool="false" />
|
||||
<PropertyValue Property="NonDeletableNavigationProperties">
|
||||
<Collection />
|
||||
</PropertyValue>
|
||||
</Record>
|
||||
</Annotation>
|
||||
</EntitySet>
|
||||
<Singleton Name="Me" Type="Microsoft.OData.SampleService.Models.TripPin.Person">
|
||||
<NavigationPropertyBinding Path="Friends" Target="People" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/Airline" Target="Airlines" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/From" Target="Airports" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Flight/To" Target="Airports" />
|
||||
<NavigationPropertyBinding Path="Photo" Target="Photos" />
|
||||
<NavigationPropertyBinding Path="Microsoft.OData.SampleService.Models.TripPin.Trip/Photos" Target="Photos" />
|
||||
<Annotation Term="Org.OData.Core.V1.ResourcePath" String="Me" />
|
||||
</Singleton>
|
||||
<FunctionImport Name="GetNearestAirport" Function="Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport" EntitySet="Airports" IncludeInServiceDocument="true">
|
||||
<Annotation Term="Org.OData.Core.V1.ResourcePath" String="Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport" />
|
||||
</FunctionImport>
|
||||
<ActionImport Name="ResetDataSource" Action="Microsoft.OData.SampleService.Models.TripPin.ResetDataSource" />
|
||||
<Annotation Term="Org.OData.Core.V1.Description" String="TripPin service is a sample service for OData V4." />
|
||||
</EntityContainer>
|
||||
<Annotations Target="Microsoft.OData.SampleService.Models.TripPin.DefaultContainer">
|
||||
<Annotation Term="Org.OData.Core.V1.DereferenceableIDs" Bool="true" />
|
||||
<Annotation Term="Org.OData.Core.V1.ConventionalIDs" Bool="true" />
|
||||
<Annotation Term="Org.OData.Capabilities.V1.ConformanceLevel">
|
||||
<EnumMember>Org.OData.Capabilities.V1.ConformanceLevelType/Advanced</EnumMember>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.SupportedFormats">
|
||||
<Collection>
|
||||
<String>application/json;odata.metadata=full;IEEE754Compatible=false;odata.streaming=true</String>
|
||||
<String>application/json;odata.metadata=minimal;IEEE754Compatible=false;odata.streaming=true</String>
|
||||
<String>application/json;odata.metadata=none;IEEE754Compatible=false;odata.streaming=true</String>
|
||||
</Collection>
|
||||
</Annotation>
|
||||
<Annotation Term="Org.OData.Capabilities.V1.AsynchronousRequestsSupported" Bool="true" />
|
||||
<Annotation Term="Org.OData.Capabilities.V1.BatchContinueOnErrorSupported" Bool="false" />
|
||||
<Annotation Term="Org.OData.Capabilities.V1.FilterFunctions">
|
||||
<Collection>
|
||||
<String>contains</String>
|
||||
<String>endswith</String>
|
||||
<String>startswith</String>
|
||||
<String>length</String>
|
||||
<String>indexof</String>
|
||||
<String>substring</String>
|
||||
<String>tolower</String>
|
||||
<String>toupper</String>
|
||||
<String>trim</String>
|
||||
<String>concat</String>
|
||||
<String>year</String>
|
||||
<String>month</String>
|
||||
<String>day</String>
|
||||
<String>hour</String>
|
||||
<String>minute</String>
|
||||
<String>second</String>
|
||||
<String>round</String>
|
||||
<String>floor</String>
|
||||
<String>ceiling</String>
|
||||
<String>cast</String>
|
||||
<String>isof</String>
|
||||
</Collection>
|
||||
</Annotation>
|
||||
</Annotations>
|
||||
</Schema>
|
||||
</edmx:DataServices>
|
||||
</edmx:Edmx>
|
Loading…
Reference in New Issue