[OLINGO-168] Tests for metadata serialization

This commit is contained in:
Christian Amend 2014-04-02 17:21:18 +02:00
parent 1e8eaecf06
commit 809519f9d8
11 changed files with 418 additions and 194 deletions

View File

@ -29,14 +29,13 @@ public abstract class AbstractEdmComplexType extends AbstractEdmStructuredType i
public AbstractEdmComplexType(
final Edm edm,
final FullQualifiedName fqn,
final FullQualifiedName typeName,
final FullQualifiedName baseTypeName) {
super(edm, fqn, EdmTypeKind.COMPLEX, baseTypeName);
super(edm, typeName, EdmTypeKind.COMPLEX, baseTypeName);
}
@Override
protected EdmStructuredType buildBaseType(final FullQualifiedName baseTypeName) {
// TODO: check for comment
EdmComplexType baseType = null;
if (baseTypeName != null) {
baseType = edm.getComplexType(baseTypeName);
@ -50,6 +49,14 @@ public abstract class AbstractEdmComplexType extends AbstractEdmStructuredType i
@Override
public EdmComplexType getBaseType() {
checkBaseType();
return (EdmComplexType) baseType;
}
@Override
protected void checkBaseType() {
if (baseTypeName != null && baseType == null) {
baseType = buildBaseType(baseTypeName);
}
}
}

View File

@ -34,19 +34,15 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
public abstract class AbstractEdmEntityType extends AbstractEdmStructuredType implements EdmEntityType {
private final boolean hasStream;
protected EdmEntityType entityBaseType;
private final List<String> keyPredicateNames = new ArrayList<String>();
private final Map<String, EdmKeyPropertyRef> keyPropertyRefs = new LinkedHashMap<String, EdmKeyPropertyRef>();
private List<EdmKeyPropertyRef> keyPropertyRefsList;
protected AbstractEdmEntityType(final Edm edm, final FullQualifiedName fqn, final FullQualifiedName baseTypeName,
protected AbstractEdmEntityType(final Edm edm, final FullQualifiedName typeName, final FullQualifiedName baseTypeName,
final boolean hashStream) {
super(edm, fqn, EdmTypeKind.ENTITY, baseTypeName);
super(edm, typeName, EdmTypeKind.ENTITY, baseTypeName);
this.hasStream = hashStream;
}
@ -76,11 +72,13 @@ public abstract class AbstractEdmEntityType extends AbstractEdmStructuredType im
@Override
public EdmEntityType getBaseType() {
checkBaseType();
return entityBaseType;
}
@Override
public List<String> getKeyPredicateNames() {
checkBaseType();
if (keyPredicateNames.isEmpty() && baseType != null) {
return entityBaseType.getKeyPredicateNames();
}
@ -89,6 +87,7 @@ public abstract class AbstractEdmEntityType extends AbstractEdmStructuredType im
@Override
public List<EdmKeyPropertyRef> getKeyPropertyRefs() {
checkBaseType();
if (keyPropertyRefsList == null) {
keyPropertyRefsList = new ArrayList<EdmKeyPropertyRef>(keyPropertyRefs.values());
}
@ -100,6 +99,7 @@ public abstract class AbstractEdmEntityType extends AbstractEdmStructuredType im
@Override
public EdmKeyPropertyRef getKeyPropertyRef(final String keyPredicateName) {
checkBaseType();
final EdmKeyPropertyRef edmKeyPropertyRef = keyPropertyRefs.get(keyPredicateName);
if (edmKeyPropertyRef == null && entityBaseType != null) {
return entityBaseType.getKeyPropertyRef(keyPredicateName);
@ -111,4 +111,8 @@ public abstract class AbstractEdmEntityType extends AbstractEdmStructuredType im
public boolean hasStream() {
return hasStream;
}
protected void checkBaseType() {
//Current Client implementation doesn`t need this so I implemented an empty body here.
}
}

View File

@ -62,7 +62,8 @@ public abstract class AbstractEdmNavigationProperty extends EdmElementImpl imple
for (String element : split) {
property = type.getNavigationProperty(element);
if (property == null) {
throw new EdmException("Cannot find property with name: " + element + " at type " + type.getName());
throw new EdmException("Cannot find navigation property with name: " + element
+ " at type " + type.getName());
}
type = (EdmStructuredType) property.getType();
}

View File

@ -35,18 +35,18 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
public abstract class AbstractEdmStructuredType extends EdmTypeImpl implements EdmStructuredType {
protected EdmStructuredType baseType;
protected FullQualifiedName baseTypeName;
private List<String> propertyNames;
private List<String> navigationPropertyNames;
public AbstractEdmStructuredType(
final Edm edm,
final FullQualifiedName fqn,
final FullQualifiedName typeName,
final EdmTypeKind kind,
final FullQualifiedName baseTypeName) {
super(edm, fqn, kind);
super(edm, typeName, kind);
this.baseTypeName = baseTypeName;
}
protected abstract EdmStructuredType buildBaseType(FullQualifiedName baseTypeName);
@ -55,10 +55,13 @@ public abstract class AbstractEdmStructuredType extends EdmTypeImpl implements E
protected abstract Map<String, EdmNavigationProperty> getNavigationProperties();
protected abstract void checkBaseType();
@Override
public List<String> getPropertyNames() {
if (propertyNames == null) {
propertyNames = new ArrayList<String>();
checkBaseType();
if (baseType != null) {
propertyNames.addAll(baseType.getPropertyNames());
}
@ -71,6 +74,7 @@ public abstract class AbstractEdmStructuredType extends EdmTypeImpl implements E
public List<String> getNavigationPropertyNames() {
if (navigationPropertyNames == null) {
navigationPropertyNames = new ArrayList<String>();
checkBaseType();
if (baseType != null) {
navigationPropertyNames.addAll(baseType.getNavigationPropertyNames());
}
@ -91,6 +95,7 @@ public abstract class AbstractEdmStructuredType extends EdmTypeImpl implements E
@Override
public EdmProperty getStructuralProperty(final String name) {
EdmProperty property = null;
checkBaseType();
if (baseType != null) {
property = baseType.getStructuralProperty(name);
}
@ -103,6 +108,7 @@ public abstract class AbstractEdmStructuredType extends EdmTypeImpl implements E
@Override
public EdmNavigationProperty getNavigationProperty(final String name) {
EdmNavigationProperty property = null;
checkBaseType();
if (baseType != null) {
property = baseType.getNavigationProperty(name);
}

View File

@ -25,19 +25,18 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
public class EdmTypeImpl extends EdmNamedImpl implements EdmType {
protected final FullQualifiedName fqn;
protected final FullQualifiedName typeName;
protected final EdmTypeKind kind;
public EdmTypeImpl(final Edm edm, final FullQualifiedName fqn, final EdmTypeKind kind) {
super(edm, fqn.getName());
this.fqn = fqn;
public EdmTypeImpl(final Edm edm, final FullQualifiedName typeName, final EdmTypeKind kind) {
super(edm, typeName.getName());
this.typeName = typeName;
this.kind = kind;
}
@Override
public String getNamespace() {
return fqn.getNamespace();
return typeName.getNamespace();
}
@Override

View File

@ -36,8 +36,6 @@ public class EdmComplexTypeImpl extends AbstractEdmComplexType {
final Edm edm, final FullQualifiedName name, final ComplexType complexType) {
final EdmComplexTypeImpl instance = new EdmComplexTypeImpl(edm, name, complexType);
instance.baseType = instance.buildBaseType(complexType.getBaseType());
return instance;
}

View File

@ -36,34 +36,19 @@ import org.apache.olingo.server.api.edm.provider.PropertyRef;
public class EdmEntityTypeImpl extends AbstractEdmEntityType {
private final EdmStructuredTypeHelper helper;
private EntityType entityType;
private boolean baseTypeChecked = false;
public static EdmEntityTypeImpl getInstance(final Edm edm, final FullQualifiedName name,
final EntityType entityType) {
final EdmEntityTypeImpl instance = new EdmEntityTypeImpl(edm, name, entityType);
instance.baseType = instance.buildBaseType(entityType.getBaseType());
if (instance.baseType == null) {
instance.entityBaseType = null;
final List<PropertyRef> key = entityType.getKey();
if (key != null) {
final List<EdmKeyPropertyRef> edmKey = new ArrayList<EdmKeyPropertyRef>();
for (PropertyRef ref : key) {
edmKey.add(new EdmKeyPropertyRefImpl(instance, ref));
}
instance.setEdmKeyPropertyRef(edmKey);
}
} else {
instance.entityBaseType = (EdmEntityType) instance.baseType;
}
return instance;
}
private EdmEntityTypeImpl(final Edm edm, final FullQualifiedName name, final EntityType entityType) {
super(edm, name, entityType.getBaseType(), entityType.hasStream());
this.entityType = entityType;
helper = new EdmStructuredTypeHelperImpl(edm, entityType);
}
@ -77,4 +62,28 @@ public class EdmEntityTypeImpl extends AbstractEdmEntityType {
return helper.getNavigationProperties();
}
@Override
protected void checkBaseType() {
if (!baseTypeChecked) {
if (baseTypeName != null) {
baseType = buildBaseType(baseTypeName);
}
if (baseType == null) {
entityBaseType = null;
final List<PropertyRef> key = entityType.getKey();
if (key != null) {
final List<EdmKeyPropertyRef> edmKey = new ArrayList<EdmKeyPropertyRef>();
for (PropertyRef ref : key) {
edmKey.add(new EdmKeyPropertyRefImpl(this, ref));
}
setEdmKeyPropertyRef(edmKey);
}
} else {
entityBaseType = (EdmEntityType) baseType;
}
baseTypeChecked = true;
}
}
}

View File

@ -155,10 +155,12 @@ public class EdmComplexTypeImplTest {
EdmProvider provider = mock(EdmProvider.class);
EdmProviderImpl edm = new EdmProviderImpl(provider);
FullQualifiedName typeWithNonexistingBaseTypeName = new FullQualifiedName("namespace", "typeName");
ComplexType complexTypeForNonexistingBaseType
= new ComplexType().setBaseType(new FullQualifiedName("wrong", "wrong"));
ComplexType complexTypeForNonexistingBaseType =
new ComplexType().setBaseType(new FullQualifiedName("wrong", "wrong"));
complexTypeForNonexistingBaseType.setName("typeName");
when(provider.getComplexType(typeWithNonexistingBaseTypeName)).thenReturn(complexTypeForNonexistingBaseType);
EdmComplexTypeImpl instance =
EdmComplexTypeImpl.getInstance(edm, typeWithNonexistingBaseTypeName, complexTypeForNonexistingBaseType);
instance.getBaseType();
}
}

View File

@ -255,7 +255,8 @@ public class EdmEntityTypeImplTest {
public void invalidBaseType() {
EdmProviderImpl edm = mock(EdmProviderImpl.class);
EntityType entityType = new EntityType().setName("n").setBaseType(new FullQualifiedName("wrong", "wrong"));
EdmEntityTypeImpl.getInstance(edm, new FullQualifiedName("n", "n"), entityType);
EdmEntityTypeImpl instance = EdmEntityTypeImpl.getInstance(edm, new FullQualifiedName("n", "n"), entityType);
instance.getBaseType();
}
@Test

View File

@ -322,12 +322,14 @@ public class EdmSchemaImplTest {
List<EntityType> entityTypes = new ArrayList<EntityType>();
entityTypes.add(new EntityType().setName("entityType1"));
entityTypes.add(new EntityType().setName("entityType2"));
entityTypes.add(new EntityType().setName("entityType2")
.setBaseType(new FullQualifiedName("namespace", "entityType1")));
providerSchema.setEntityTypes(entityTypes);
List<ComplexType> complexTypes = new ArrayList<ComplexType>();
complexTypes.add(new ComplexType().setName("complexType1"));
complexTypes.add(new ComplexType().setName("complexType2"));
complexTypes.add(new ComplexType().setName("complexType2").setBaseType(
new FullQualifiedName("namespace", "complexType1")));
providerSchema.setComplexTypes(complexTypes);
List<Action> actions = new ArrayList<Action>();

View File

@ -18,13 +18,41 @@
*/
package org.apache.olingo.server.core.serializer.xml;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.olingo.commons.api.ODataException;
import org.apache.olingo.commons.api.ODataRuntimeException;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.Target;
import org.apache.olingo.server.api.ODataServer;
import org.apache.olingo.server.api.edm.provider.Action;
import org.apache.olingo.server.api.edm.provider.ActionImport;
import org.apache.olingo.server.api.edm.provider.ComplexType;
import org.apache.olingo.server.api.edm.provider.EdmProvider;
import org.apache.olingo.server.api.edm.provider.EntityContainer;
import org.apache.olingo.server.api.edm.provider.EntitySet;
import org.apache.olingo.server.api.edm.provider.EntityType;
import org.apache.olingo.server.api.edm.provider.EnumMember;
import org.apache.olingo.server.api.edm.provider.EnumType;
import org.apache.olingo.server.api.edm.provider.Function;
import org.apache.olingo.server.api.edm.provider.FunctionImport;
import org.apache.olingo.server.api.edm.provider.NavigationProperty;
import org.apache.olingo.server.api.edm.provider.NavigationPropertyBinding;
import org.apache.olingo.server.api.edm.provider.Parameter;
import org.apache.olingo.server.api.edm.provider.Property;
import org.apache.olingo.server.api.edm.provider.ReturnType;
import org.apache.olingo.server.api.edm.provider.Schema;
import org.apache.olingo.server.api.edm.provider.Singleton;
import org.apache.olingo.server.api.edm.provider.TypeDefinition;
import org.apache.olingo.server.api.serializer.ODataFormat;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.core.edm.provider.EdmProviderImpl;
@ -47,11 +75,178 @@ public class MetadataDocumentTest {
serializer.metadataDocument(edm);
}
@Test
public void writeMetadataWithLocalTestEdm() {
ODataSerializer serializer = ODataServer.newInstance().getSerializer(ODataFormat.XML);
Edm edm = new EdmProviderImpl(new TestMetadataProvider());
InputStream metadata = serializer.metadataDocument(edm);
assertNotNull(metadata);
String metadataString = StringUtils.inputStreamToString(metadata, false);
assertTrue(metadataString
.contains("<edmx:Edmx Version=\"4.0\" xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\">"));
assertTrue(metadataString
.contains("<Schema xmlns=\"http://docs.oasis-open.org/odata/ns/edm\" " +
"Namespace=\"namespace\" Alias=\"alias\">"));
assertTrue(metadataString
.contains("<EntityType Name=\"ETBaseName\"><Property Name=\"P1\" Type=\"Edm.Int16\"/><NavigationProperty " +
"Name=\"N1\" Type=\"namespace.ETBaseName\" Nullable=\"true\" Partner=\"N1\"/></EntityType>"));
assertTrue(metadataString
.contains("<EntityType Name=\"ETDerivedName\" BaseType=\"namespace.ETBaseName\"><Property Name=\"P2\" " +
"Type=\"Edm.Int16\"/><NavigationProperty Name=\"N2\" Type=\"namespace.ETDerivedName\" Nullable=\"true\" " +
"Partner=\"N2\"/></EntityType>"));
assertTrue(metadataString
.contains("<ComplexType Name=\"CTBaseName\"><Property Name=\"P1\" Type=\"Edm.Int16\"/><NavigationProperty " +
"Name=\"N1\" Type=\"namespace.ETBaseName\" Nullable=\"true\" Partner=\"N1\"/></ComplexType>"));
assertTrue(metadataString
.contains("<ComplexType Name=\"CTDerivedName\" BaseType=\"namespace.CTBaseName\"><Property Name=\"P2\" " +
"Type=\"Edm.Int16\"/><NavigationProperty Name=\"N2\" Type=\"namespace.ETDerivedName\" Nullable=\"true\" " +
"Partner=\"N2\"/></ComplexType>"));
assertTrue(metadataString.contains("<TypeDefinition Name=\"typeDef\" Type=\"Edm.Int16\"/>"));
assertTrue(metadataString.contains("<Action Name=\"ActionWOParameter\" IsBound=\"false\"/>"));
assertTrue(metadataString
.contains("<Action Name=\"ActionName\" IsBound=\"true\"><Parameter Name=\"param\" Type=\"Edm.Int16\"/>" +
"<Parameter Name=\"param2\" Type=\"Collection(Edm.Int16)\"/><ReturnType Type=\"namespace.CTBaseName\"/>" +
"</Action>"));
assertTrue(metadataString
.contains("<Function Name=\"FunctionWOParameter\" IsBound=\"false\" IsComposable=\"false\"><ReturnType " +
"Type=\"namespace.CTBaseName\"/></Function>"));
assertTrue(metadataString
.contains("<Function Name=\"FunctionName\" IsBound=\"true\" IsComposable=\"false\"><Parameter Name=\"param\" " +
"Type=\"Edm.Int16\"/><Parameter Name=\"param2\" Type=\"Collection(Edm.Int16)\"/><ReturnType " +
"Type=\"namespace.CTBaseName\"/></Function>"));
assertTrue(metadataString.contains("<EntityContainer Name=\"container\">"));
assertTrue(metadataString
.contains("<EntitySet Name=\"EntitySetName\" EntityType=\"namespace.ETBaseName\"><NavigationPropertyBinding " +
"Path=\"N1\" Target=\"namespace.container/EntitySetName\"/></EntitySet>"));
assertTrue(metadataString
.contains("<Singleton Name=\"SingletonName\" EntityType=\"namespace.ETBaseName\"><NavigationPropertyBinding " +
"Path=\"N1\" Target=\"namespace.container/EntitySetName\"/></Singleton>"));
assertTrue(metadataString.contains("<ActionImport Name=\"actionImport\" Action=\"namespace.ActionWOParameter\"/>"));
assertTrue(metadataString
.contains("<FunctionImport Name=\"actionImport\" Function=\"namespace.FunctionName\" " +
"EntitySet=\"namespace.EntitySetName\" IncludeInServiceDocument=\"false\"/>"));
assertTrue(metadataString.contains("</EntityContainer></Schema></edmx:DataServices></edmx:Edmx>"));
}
@Test
public void writeMetadataWithTechnicalScenario() {
ODataSerializer serializer = ODataServer.newInstance().getSerializer(ODataFormat.XML);
EdmProviderImpl edm = new EdmProviderImpl(new EdmTechProvider());
InputStream metadata = serializer.metadataDocument(edm);
StringUtils.inputStreamToString(metadata, false);
assertNotNull(metadata);
// The technical scenario is too big to verify. We are content for now to make sure we can serialize it.
// System.out.println(StringUtils.inputStreamToString(metadata, false));
}
private class TestMetadataProvider extends EdmProvider {
@Override
public List<Schema> getSchemas() throws ODataException {
Property p1 = new Property().setName("P1").setType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName());
String ns = "namespace";
NavigationProperty n1 = new NavigationProperty().setName("N1")
.setType(new FullQualifiedName(ns, "ETBaseName")).setNullable(true).setPartner("N1");
Property p2 = new Property().setName("P2").setType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName());
NavigationProperty n2 = new NavigationProperty().setName("N2")
.setType(new FullQualifiedName(ns, "ETDerivedName")).setNullable(true).setPartner("N2");
Schema schema = new Schema().setNamespace(ns).setAlias("alias");
List<ComplexType> complexTypes = new ArrayList<ComplexType>();
schema.setComplexTypes(complexTypes);
ComplexType ctBase =
new ComplexType().setName("CTBaseName").setProperties(Arrays.asList(p1)).setNavigationProperties(
Arrays.asList(n1));
complexTypes.add(ctBase);
ComplexType ctDerived =
new ComplexType().setName("CTDerivedName").setBaseType(new FullQualifiedName(ns, "CTBaseName"))
.setProperties(Arrays.asList(p2)).setNavigationProperties(Arrays.asList(n2));
complexTypes.add(ctDerived);
List<EntityType> entityTypes = new ArrayList<EntityType>();
schema.setEntityTypes(entityTypes);
EntityType etBase =
new EntityType().setName("ETBaseName").setProperties(Arrays.asList(p1)).setNavigationProperties(
Arrays.asList(n1));
entityTypes.add(etBase);
EntityType etDerived =
new EntityType().setName("ETDerivedName").setBaseType(new FullQualifiedName(ns, "ETBaseName"))
.setProperties(Arrays.asList(p2)).setNavigationProperties(Arrays.asList(n2));
entityTypes.add(etDerived);
List<Action> actions = new ArrayList<Action>();
schema.setActions(actions);
// TODO:EntitySetPath
actions.add((new Action().setName("ActionWOParameter")));
List<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter().setName("param").setType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName()));
parameters.add(new Parameter().setName("param2").setType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName())
.setCollection(true));
actions.add(new Action().setName("ActionName").setBound(true).setParameters(parameters).setReturnType(
new ReturnType().setType(new FullQualifiedName(ns, "CTBaseName"))));
List<Function> functions = new ArrayList<Function>();
schema.setFunctions(functions);
functions.add((new Function().setName("FunctionWOParameter")
.setReturnType(new ReturnType().setType(new FullQualifiedName(ns, "CTBaseName")))));
functions.add(new Function().setName("FunctionName").setBound(true).setParameters(parameters).setReturnType(
new ReturnType().setType(new FullQualifiedName(ns, "CTBaseName"))));
List<EnumType> enumTypes = new ArrayList<EnumType>();
schema.setEnumTypes(enumTypes);
List<EnumMember> members = new ArrayList<EnumMember>();
members.add(new EnumMember().setName("member").setValue("1"));
enumTypes.add(new EnumType().setName("EnumName").setFlags(true).setMembers(members));
List<TypeDefinition> typeDefinitions = new ArrayList<TypeDefinition>();
schema.setTypeDefinitions(typeDefinitions);
typeDefinitions.add(new TypeDefinition().setName("typeDef")
.setUnderlyingType(EdmPrimitiveTypeKind.Int16.getFullQualifiedName()));
EntityContainer container = new EntityContainer().setName("container");
schema.setEntityContainer(container);
List<ActionImport> actionImports = new ArrayList<ActionImport>();
container.setActionImports(actionImports);
actionImports.add(new ActionImport().setName("actionImport").setAction(
new FullQualifiedName(ns, "ActionWOParameter")).setEntitySet(
new Target().setEntityContainer(new FullQualifiedName(ns, "container")).setTargetName("EntitySetName")));
List<FunctionImport> functionImports = new ArrayList<FunctionImport>();
container.setFunctionImports(functionImports);
functionImports.add(new FunctionImport().setName("actionImport").setFunction(
new FullQualifiedName(ns, "FunctionName")).setEntitySet(
new Target().setEntityContainer(new FullQualifiedName(ns, "container")).setTargetName("EntitySetName")));
List<EntitySet> entitySets = new ArrayList<EntitySet>();
container.setEntitySets(entitySets);
List<NavigationPropertyBinding> nPB = new ArrayList<NavigationPropertyBinding>();
nPB.add(new NavigationPropertyBinding().setPath("N1").setTarget(
new Target().setEntityContainer(new FullQualifiedName(ns, "container")).setTargetName("EntitySetName")));
entitySets.add(new EntitySet().setName("EntitySetName").setType(new FullQualifiedName(ns, "ETBaseName"))
.setNavigationPropertyBindings(nPB));
List<Singleton> singletons = new ArrayList<Singleton>();
container.setSingletons(singletons);
singletons.add(new Singleton().setName("SingletonName").setType(new FullQualifiedName(ns, "ETBaseName"))
.setNavigationPropertyBindings(nPB));
List<Schema> schemas = new ArrayList<Schema>();
schemas.add(schema);
return schemas;
}
}
}