Merge branch 'master' into olingo472

Conflicts:
	lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
	lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
	lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
This commit is contained in:
Christian Amend 2014-11-13 17:27:36 +01:00
commit 4f820fe533
42 changed files with 2070 additions and 1153 deletions

View File

@ -22,6 +22,7 @@ import org.apache.olingo.commons.api.ODataRuntimeException;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.server.api.edm.provider.EdmProvider;
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.SerializerException;
@ -57,10 +58,16 @@ public abstract class OData {
* Creates a new serializer object for rendering content in the specified format.
* Serializers are used in Processor implementations.
*
* @param format - any format supported by Olingo (XML, JSON ...)
* @param format any format supported by Olingo (XML, JSON ...)
*/
public abstract ODataSerializer createSerializer(ODataFormat format) throws SerializerException;
/**
* Creates a new serializer object for rendering content in a fixed format, e.g., for binary output.
* Serializers are used in Processor implementations.
*/
public abstract FixedFormatSerializer createFixedFormatSerializer() throws SerializerException;
/**
* Creates a new ODataHttpHandler for handling OData requests in an HTTP context.
*

View File

@ -0,0 +1,46 @@
/*
* 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.server.api.processor;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling a collection of complex-type instances, e.g.,
* a property of an entity defined as collection of complex-type instances.
*/
public interface ComplexCollectionProcessor extends Processor {
/**
* Reads complex-type collection.
* If it is not available, for example due to permissions, the service responds with 404 Not Found.
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readComplexCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -0,0 +1,45 @@
/*
* 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.server.api.processor;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling an instance of a complex type, e.g., a complex property of an entity.
*/
public interface ComplexProcessor extends Processor {
/**
* Reads complex-type instance.
* If it is not available, for example due to permissions, the service responds with 404 Not Found.
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -0,0 +1,45 @@
/*
* 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.server.api.processor;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling counting a collection of entities, e.g., an Entity Set.
*/
public interface CountEntityCollectionProcessor extends Processor {
/**
* Counts entities from persistence and puts serialized content and status into the response.
* Response content type is <code>text/plain</code> by default.
* @param request OData request object containing raw HTTP information.
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void countEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -26,33 +26,19 @@ import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling EntitySets (i.e. collection of entities).
* Processor interface for handling a collection of entities, e.g., an Entity Set.
*/
public interface EntitySetProcessor extends Processor {
public interface EntityCollectionProcessor extends Processor {
/**
* Reads entities data from persistence and puts serialized content and status into the response.
*
* @param request - OData request object containing raw HTTP information
* @param response - OData response object for collecting response data
* @param uriInfo - information of a parsed OData URI
* @param requestedContentType - requested content type after content negotiation
* @throws ODataApplicationException
* @throws SerializerException
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readEntitySet(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestedContentType)
void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
/**
* Count entities from persistence and puts serialized content and status into the response.
* Response content type is <code>text/plain</code> by default.
*
* @param request - OData request object containing raw http information.
* @param response - OData response object for collecting response data
* @param uriInfo - information of a parsed OData uri
* @throws ODataApplicationException
* @throws SerializerException
*/
void countEntitySet(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException,
SerializerException;
}

View File

@ -26,19 +26,19 @@ import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling a single Entity.
* Processor interface for handling a single instance of an Entity Type.
*/
public interface EntityProcessor extends Processor {
/**
* Reads entity data from persistence and puts serialized content and status into the response.
* @param request - OData request object containing raw HTTP information
* @param response - OData response object for collecting response data
* @param uriInfo - information of a parsed OData URI
* @param requestedContentType - requested content type after content negotiation
* @throws ODataApplicationException
* @throws SerializerException
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestedContentType)
void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -30,11 +30,11 @@ public interface ExceptionProcessor extends Processor {
/**
* Processes an exception. MUST NOT throw an exception!
* @param request the request
* @param response the response
* @param serverError the server error
* @param requestedContentType the requested format for the error message
* @param request the request
* @param response the response
* @param serverError the server error
* @param format the requested format for the error message
*/
public void processException(ODataRequest request, ODataResponse response, ODataServerError serverError,
ContentType requestedContentType);
ContentType format);
}

View File

@ -32,13 +32,13 @@ public interface MetadataProcessor extends Processor {
/**
* Reads data from persistency and puts serialized content and status into the response.
* @param request - OData request object containing raw HTTP information
* @param response - OData response object for collecting response data
* @param uriInfo - information of a parsed OData URI
* @param requestedContentType - requested content type after content negotiation
* @throws ODataApplicationException
* @throws SerializerException
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readMetadata(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestedContentType)
void readMetadata(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -0,0 +1,46 @@
/*
* 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.server.api.processor;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling a collection of primitive-type instances, e.g.,
* a property of an entity defined as collection of primitive-type instances.
*/
public interface PrimitiveCollectionProcessor extends Processor {
/**
* Reads primitive-type collection.
* If it is not available, for example due to permissions, the service responds with 404 Not Found.
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -0,0 +1,60 @@
/*
* 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.server.api.processor;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling an instance of a primitive type, e.g., a primitive property of an entity.
*/
public interface PrimitiveProcessor extends Processor {
/**
* Reads primitive-type instance.
* If its value is <code>null</code>, the service responds with 204 No Content.
* If it is not available, for example due to permissions, the service responds with 404 Not Found.
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readPrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
/**
* Reads raw value of a primitive-type instance, e.g., of a primitive property of an entity.
* If the value is <code>null</code>, the service responds with 204 No Content.
* If it is not available, for example due to permissions, the service responds with 404 Not Found.
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readPrimitiveAsValue(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -1,62 +0,0 @@
/*
* 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.server.api.processor;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
/**
* Processor interface for handling a property of an entity.
*/
public interface PropertyProcessor extends Processor {
/**
* Reads primitive or complex property from entity.
* If the property is single-valued and has the null value, the service responds with 204 No Content.
* If the property is not available, for example due to permissions, the service responds with 404 Not Found
*
* @param request - OData request object containing raw HTTP information
* @param response - OData response object for collecting response data
* @param uriInfo - information of a parsed OData URI
* @param format - requested content type after content negotiation
* @throws ODataApplicationException if service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readProperty(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
/**
* Reads value for primitive property from entity.
* If the property is single-valued and has the null value, the service responds with 204 No Content.
* If the property is not available, for example due to permissions, the service responds with 404 Not Found
*
* @param request - OData request object containing raw HTTP information
* @param response - OData response object for collecting response data
* @param uriInfo - information of a parsed OData URI
* @param format - requested content type after content negotiation
* @throws ODataApplicationException if service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readPropertyValue(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -32,11 +32,13 @@ public interface ServiceDocumentProcessor extends Processor {
/**
* Reads service-document information from persistency and puts serialized content and status into the response.
* @param request - OData request object containing raw HTTP information
* @param response - OData response object for collecting response data
* @param uriInfo - information of a parsed OData URI
* @param requestedContentType - requested content type after content negotiation
* @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI
* @param format requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void readServiceDocument(ODataRequest request, ODataResponse response, UriInfo uriInfo,
ContentType requestedContentType) throws ODataApplicationException, SerializerException;
void readServiceDocument(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException;
}

View File

@ -0,0 +1,86 @@
/*
* 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.server.api.serializer;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
/** Options for the OData serializer. */
public class ComplexSerializerOptions {
private ContextURL contextURL;
private ExpandOption expand;
private SelectOption select;
/** Gets the {@link ContextURL}. */
public ContextURL getContextURL() {
return contextURL;
}
/** Gets the $expand system query option. */
public ExpandOption getExpand() {
return expand;
}
/** Gets the $select system query option. */
public SelectOption getSelect() {
return select;
}
private ComplexSerializerOptions() {}
/** Initializes the options builder. */
public static Builder with() {
return new Builder();
}
/** Builder of OData serializer options. */
public static final class Builder {
private ComplexSerializerOptions options;
private Builder() {
options = new ComplexSerializerOptions();
}
/** Sets the {@link ContextURL}. */
public Builder contextURL(final ContextURL contextURL) {
options.contextURL = contextURL;
return this;
}
/** Sets the $expand system query option. */
public Builder expand(final ExpandOption expand) {
options.expand = expand;
return this;
}
/** Sets the $select system query option. */
public Builder select(final SelectOption select) {
options.select = select;
return this;
}
/** Builds the OData serializer options. */
public ComplexSerializerOptions build() {
return options;
}
}
}

View File

@ -24,7 +24,7 @@ import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
/** Options for the OData serializer. */
public class ODataSerializerOptions {
public class EntityCollectionSerializerOptions {
private ContextURL contextURL;
private CountOption count;
@ -51,8 +51,6 @@ public class ODataSerializerOptions {
return select;
}
private ODataSerializerOptions() {}
/** Initializes the options builder. */
public static Builder with() {
return new Builder();
@ -61,10 +59,10 @@ public class ODataSerializerOptions {
/** Builder of OData serializer options. */
public static final class Builder {
private ODataSerializerOptions options;
private EntityCollectionSerializerOptions options;
private Builder() {
options = new ODataSerializerOptions();
options = new EntityCollectionSerializerOptions();
}
/** Sets the {@link ContextURL}. */
@ -92,7 +90,7 @@ public class ODataSerializerOptions {
}
/** Builds the OData serializer options. */
public ODataSerializerOptions build() {
public EntityCollectionSerializerOptions build() {
return options;
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.server.api.serializer;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
/** Options for the OData serializer. */
public class EntitySerializerOptions {
private ContextURL contextURL;
private ExpandOption expand;
private SelectOption select;
/** Gets the {@link ContextURL}. */
public ContextURL getContextURL() {
return contextURL;
}
/** Gets the $expand system query option. */
public ExpandOption getExpand() {
return expand;
}
/** Gets the $select system query option. */
public SelectOption getSelect() {
return select;
}
private EntitySerializerOptions() {}
/** Initializes the options builder. */
public static final Builder with() {
return new Builder();
}
/** Builder of OData serializer options. */
public static final class Builder {
private EntitySerializerOptions options;
private Builder() {
options = new EntitySerializerOptions();
}
/** Sets the {@link ContextURL}. */
public Builder contextURL(final ContextURL contextURL) {
options.contextURL = contextURL;
return this;
}
/** Sets the $expand system query option. */
public Builder expand(final ExpandOption expand) {
options.expand = expand;
return this;
}
/** Sets the $select system query option. */
public Builder select(final SelectOption select) {
options.select = select;
return this;
}
/** Builds the OData serializer options. */
public EntitySerializerOptions build() {
return options;
}
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.server.api.serializer;
import java.io.InputStream;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
/** OData serializer for fixed output formats. */
public interface FixedFormatSerializer {
/**
* Writes binary output into an InputStream.
* @param binary the binary data
*/
InputStream binary(byte[] binary) throws SerializerException;
/**
* Writes a count into an InputStream as plain text.
* @param count the count
*/
InputStream count(Integer count) throws SerializerException;
/**
* Writes the raw value of a primitive-type instance into an InputStream.
* @param type the primitive type
* @param value the value
* @param options options for the serializer
*/
InputStream primitiveValue(EdmPrimitiveType type, Object value, PrimitiveValueSerializerOptions options)
throws SerializerException;
}

View File

@ -25,8 +25,10 @@ import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.uri.UriParameter;
@ -52,33 +54,6 @@ public interface ODataSerializer {
*/
InputStream metadataDocument(ServiceMetadata serviceMetadata) throws SerializerException;
/**
* Writes entity data into an InputStream.
* @param edmEntitySet the {@link EdmEntitySet}
* @param entity the data of the entity
* @param options options for the serializer
*/
InputStream entity(EdmEntitySet edmEntitySet, Entity entity, ODataSerializerOptions options)
throws SerializerException;
/**
* Writes entity data into an InputStream.
* @param edmProperty property definition
* @param property property value
* @param options options for the serializer
*/
InputStream entityProperty(EdmProperty edmProperty, Property property, ODataSerializerOptions options)
throws SerializerException;
/**
* Writes entity-set data into an InputStream.
* @param edmEntitySet the {@link EdmEntitySet}
* @param entitySet the data of the entity set
* @param options options for the serializer
*/
InputStream entitySet(EdmEntitySet edmEntitySet, EntitySet entitySet, ODataSerializerOptions options)
throws SerializerException;
/**
* Writes an ODataError into an InputStream.
* @param error the main error
@ -86,14 +61,68 @@ public interface ODataSerializer {
*/
InputStream error(ODataServerError error) throws SerializerException;
/**
* Writes entity-collection data into an InputStream.
* @param entityType the {@link EdmEntityType}
* @param entitySet the data of the entity set
* @param options options for the serializer
*/
InputStream entityCollection(EdmEntityType entityType, EntitySet entitySet,
EntityCollectionSerializerOptions options) throws SerializerException;
/**
* Writes entity data into an InputStream.
* @param entityType the {@link EdmEntityType}
* @param entity the data of the entity
* @param options options for the serializer
*/
InputStream entity(EdmEntityType entityType, Entity entity, EntitySerializerOptions options)
throws SerializerException;
/**
* Writes primitive-type instance data into an InputStream.
* @param type primitive type
* @param property property value
* @param options options for the serializer
*/
InputStream primitive(EdmPrimitiveType type, Property property, PrimitiveSerializerOptions options)
throws SerializerException;
/**
* Writes complex-type instance data into an InputStream.
* @param type complex type
* @param property property value
* @param options options for the serializer
*/
InputStream complex(EdmComplexType type, Property property, ComplexSerializerOptions options)
throws SerializerException;
/**
* Writes data of a collection of primitive-type instances into an InputStream.
* @param type primitive type
* @param property property value
* @param options options for the serializer
*/
InputStream primitiveCollection(EdmPrimitiveType type, Property property, PrimitiveSerializerOptions options)
throws SerializerException;
/**
* Writes data of a collection of complex-type instances into an InputStream.
* @param type complex type
* @param property property value
* @param options options for the serializer
*/
InputStream complexCollection(EdmComplexType type, Property property, ComplexSerializerOptions options)
throws SerializerException;
/**
* Builds the select-list part of a {@link org.apache.olingo.commons.api.data.ContextURL ContextURL}.
* @param edmEntitySet the Entity Set
* @param expand the $expand option
* @param select the $select option
* @param type the {@link EdmStructuredType}
* @param expand the $expand option
* @param select the $select option
* @return a String with the select list
*/
String buildContextURLSelectList(EdmEntitySet edmEntitySet, ExpandOption expand, SelectOption select)
String buildContextURLSelectList(EdmStructuredType type, ExpandOption expand, SelectOption select)
throws SerializerException;
/**

View File

@ -0,0 +1,131 @@
/*
* 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.server.api.serializer;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.edm.EdmProperty;
/** Options for the OData serializer. */
public class PrimitiveSerializerOptions {
private ContextURL contextURL;
private Boolean isNullable;
private Integer maxLength;
private Integer precision;
private Integer scale;
private Boolean isUnicode;
/** Gets the {@link ContextURL}. */
public ContextURL getContextURL() {
return contextURL;
}
/** Gets the nullable facet. */
public Boolean isNullable() {
return isNullable;
}
/** Gets the maxLength facet. */
public Integer getMaxLength() {
return maxLength;
}
/** Gets the precision facet. */
public Integer getPrecision() {
return precision;
}
/** Gets the scale facet. */
public Integer getScale() {
return scale;
}
/** Gets the unicode facet. */
public Boolean isUnicode() {
return isUnicode;
}
private PrimitiveSerializerOptions() {}
/** Initializes the options builder. */
public static Builder with() {
return new Builder();
}
/** Builder of OData serializer options. */
public static final class Builder {
private PrimitiveSerializerOptions options;
private Builder() {
options = new PrimitiveSerializerOptions();
}
/** Sets the {@link ContextURL}. */
public Builder contextURL(final ContextURL contextURL) {
options.contextURL = contextURL;
return this;
}
/** Sets the nullable facet. */
public Builder nullable(final Boolean isNullable) {
options.isNullable = isNullable;
return this;
}
/** Sets the maxLength facet. */
public Builder maxLength(final Integer maxLength) {
options.maxLength = maxLength;
return this;
}
/** Sets the precision facet. */
public Builder precision(final Integer precision) {
options.precision = precision;
return this;
}
/** Sets the scale facet. */
public Builder scale(final Integer scale) {
options.scale = scale;
return this;
}
/** Sets the unicode facet. */
public Builder unicode(final Boolean isUnicode) {
options.isUnicode = isUnicode;
return this;
}
/** Sets all facets from an EDM property. */
public Builder facetsFrom(final EdmProperty property) {
options.isNullable = property.isNullable();
options.maxLength = property.getMaxLength();
options.precision = property.getPrecision();
options.scale = property.getScale();
options.isUnicode = property.isUnicode();
return this;
}
/** Builds the OData serializer options. */
public PrimitiveSerializerOptions build() {
return options;
}
}
}

View File

@ -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.server.api.serializer;
import org.apache.olingo.commons.api.edm.EdmProperty;
/** Options for the OData serializer. */
public class PrimitiveValueSerializerOptions {
private Boolean isNullable;
private Integer maxLength;
private Integer precision;
private Integer scale;
private Boolean isUnicode;
/** Gets the nullable facet. */
public Boolean isNullable() {
return isNullable;
}
/** Gets the maxLength facet. */
public Integer getMaxLength() {
return maxLength;
}
/** Gets the precision facet. */
public Integer getPrecision() {
return precision;
}
/** Gets the scale facet. */
public Integer getScale() {
return scale;
}
/** Gets the unicode facet. */
public Boolean isUnicode() {
return isUnicode;
}
private PrimitiveValueSerializerOptions() {}
/** Initializes the options builder. */
public static Builder with() {
return new Builder();
}
/** Builder of OData serializer options. */
public static final class Builder {
private PrimitiveValueSerializerOptions options;
private Builder() {
options = new PrimitiveValueSerializerOptions();
}
/** Sets the nullable facet. */
public Builder nullable(final Boolean isNullable) {
options.isNullable = isNullable;
return this;
}
/** Sets the maxLength facet. */
public Builder maxLength(final Integer maxLength) {
options.maxLength = maxLength;
return this;
}
/** Sets the precision facet. */
public Builder precision(final Integer precision) {
options.precision = precision;
return this;
}
/** Sets the scale facet. */
public Builder scale(final Integer scale) {
options.scale = scale;
return this;
}
/** Sets the unicode facet. */
public Builder unicode(final Boolean isUnicode) {
options.isUnicode = isUnicode;
return this;
}
/** Sets all facets from an EDM property. */
public Builder facetsFrom(final EdmProperty property) {
options.isNullable = property.isNullable();
options.maxLength = property.getMaxLength();
options.precision = property.getPrecision();
options.scale = property.getScale();
options.isUnicode = property.isUnicode();
return this;
}
/** Builds the OData serializer options. */
public PrimitiveValueSerializerOptions build() {
return options;
}
}
}

View File

@ -36,7 +36,8 @@ public class SerializerException extends ODataTranslatedException {
/** parameter: property name */ UNSUPPORTED_PROPERTY_TYPE,
/** parameter: property name */ INCONSISTENT_PROPERTY_TYPE,
/** parameter: property name */ MISSING_PROPERTY,
/** parameters: property name, property value */ WRONG_PROPERTY_VALUE;
/** parameters: property name, property value */ WRONG_PROPERTY_VALUE,
/** parameters: primitive-type name, value */ WRONG_PRIMITIVE_VALUE;
@Override
public String getKey() {

View File

@ -37,20 +37,24 @@ import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.batch.BatchException;
import org.apache.olingo.server.api.processor.BatchProcessor;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.DefaultProcessor;
import org.apache.olingo.server.api.processor.EntitySetProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.ExceptionProcessor;
import org.apache.olingo.server.api.processor.MetadataProcessor;
import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.processor.PropertyProcessor;
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
import org.apache.olingo.server.api.serializer.RepresentationType;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceNavigation;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.UriResourceProperty;
@ -130,11 +134,10 @@ public class ODataHandler {
switch (uriInfo.getKind()) {
case metadata:
if (method.equals(HttpMethod.GET)) {
MetadataProcessor mp = selectProcessor(MetadataProcessor.class);
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, RepresentationType.METADATA);
mp.readMetadata(request, response, uriInfo, requestedContentType);
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.METADATA);
selectProcessor(MetadataProcessor.class)
.readMetadata(request, response, uriInfo, requestedContentType);
} else {
throw new ODataHandlerException("HttpMethod " + method + " not allowed for metadata document",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
@ -143,15 +146,13 @@ public class ODataHandler {
case service:
if (method.equals(HttpMethod.GET)) {
if ("".equals(request.getRawODataPath())) {
RedirectProcessor rdp = selectProcessor(RedirectProcessor.class);
rdp.redirect(request, response);
selectProcessor(RedirectProcessor.class).redirect(request, response);
} else {
ServiceDocumentProcessor sdp = selectProcessor(ServiceDocumentProcessor.class);
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.SERVICE);
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, RepresentationType.SERVICE);
sdp.readServiceDocument(request, response, uriInfo, requestedContentType);
selectProcessor(ServiceDocumentProcessor.class)
.readServiceDocument(request, response, uriInfo, requestedContentType);
}
} else {
throw new ODataHandlerException("HttpMethod " + method + " not allowed for service document",
@ -195,113 +196,118 @@ public class ODataHandler {
private void handleResourceDispatching(final ODataRequest request, final ODataResponse response)
throws ODataHandlerException, ContentNegotiatorException, ODataApplicationException, SerializerException {
final HttpMethod method = request.getMethod();
final int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
final UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
switch (lastPathSegment.getKind()) {
case entitySet:
if (((UriResourcePartTyped) lastPathSegment).isCollection()) {
if (request.getMethod().equals(HttpMethod.GET)) {
EntitySetProcessor cp = selectProcessor(EntitySetProcessor.class);
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, RepresentationType.COLLECTION_ENTITY);
cp.readEntitySet(request, response, uriInfo, requestedContentType);
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
} else {
if (request.getMethod().equals(HttpMethod.GET)) {
EntityProcessor ep = selectProcessor(EntityProcessor.class);
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, RepresentationType.ENTITY);
ep.readEntity(request, response, uriInfo, requestedContentType);
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
}
break;
case navigationProperty:
if (((UriResourceNavigation) lastPathSegment).isCollection()) {
if (request.getMethod().equals(HttpMethod.GET)) {
EntitySetProcessor cp = selectProcessor(EntitySetProcessor.class);
if (((UriResourcePartTyped) lastPathSegment).isCollection()) {
if (method.equals(HttpMethod.GET)) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.COLLECTION_ENTITY);
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, RepresentationType.COLLECTION_ENTITY);
cp.readEntitySet(request, response, uriInfo, requestedContentType);
selectProcessor(EntityCollectionProcessor.class)
.readEntityCollection(request, response, uriInfo, requestedContentType);
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
} else {
if (request.getMethod().equals(HttpMethod.GET)) {
EntityProcessor ep = selectProcessor(EntityProcessor.class);
if (method.equals(HttpMethod.GET)) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY);
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, RepresentationType.ENTITY);
ep.readEntity(request, response, uriInfo, requestedContentType);
selectProcessor(EntityProcessor.class)
.readEntity(request, response, uriInfo, requestedContentType);
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
}
break;
case count:
if (request.getMethod().equals(HttpMethod.GET)) {
EntitySetProcessor cp = selectProcessor(EntitySetProcessor.class);
cp.countEntitySet(request, response, uriInfo);
if (method.equals(HttpMethod.GET)) {
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) {
selectProcessor(CountEntityCollectionProcessor.class)
.countEntityCollection(request, response, uriInfo, ContentType.TEXT_PLAIN);
} else {
throw new ODataHandlerException(
"Count of collections of primitive-type or complex-type instances is not implemented.",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
break;
case primitiveProperty:
case complexProperty:
if (request.getMethod().equals(HttpMethod.GET)) {
PropertyProcessor ep = selectProcessor(PropertyProcessor.class);
if (method.equals(HttpMethod.GET)) {
final UriResourceProperty propertyResource = (UriResourceProperty) lastPathSegment;
final boolean isCollection = propertyResource.isCollection();
final boolean isComplex = propertyResource.getKind() == UriResourceKind.complexProperty;
final RepresentationType representationType =
isComplex ? isCollection ? RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX :
isCollection ? RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE;
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, representationType);
ep.readProperty(request, response, uriInfo, requestedContentType);
final RepresentationType representationType = propertyResource.isCollection() ?
RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE;
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, representationType);
if (representationType == RepresentationType.PRIMITIVE) {
selectProcessor(PrimitiveProcessor.class)
.readPrimitive(request, response, uriInfo, requestedContentType);
} else {
selectProcessor(PrimitiveCollectionProcessor.class)
.readPrimitiveCollection(request, response, uriInfo, requestedContentType);
}
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
break;
case complexProperty:
if (method.equals(HttpMethod.GET)) {
final UriResourceProperty propertyResource = (UriResourceProperty) lastPathSegment;
final RepresentationType representationType = propertyResource.isCollection() ?
RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX;
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, representationType);
if (representationType == RepresentationType.COMPLEX) {
selectProcessor(ComplexProcessor.class)
.readComplex(request, response, uriInfo, requestedContentType);
} else {
selectProcessor(ComplexCollectionProcessor.class)
.readComplexCollection(request, response, uriInfo, requestedContentType);
}
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
break;
case value:
if (request.getMethod().equals(HttpMethod.GET)) {
PropertyProcessor ep = selectProcessor(PropertyProcessor.class);
if (method.equals(HttpMethod.GET)) {
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
if (resource instanceof UriResourceProperty) {
final RepresentationType representationType =
(EdmPrimitiveType) ((UriResourceProperty) resource).getType() ==
EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
RepresentationType.BINARY : RepresentationType.VALUE;
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, representationType);
final UriResourceProperty propertyResource =
(UriResourceProperty) uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
final RepresentationType representationType =
(EdmPrimitiveType) propertyResource.getType() ==
EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
RepresentationType.BINARY :
RepresentationType.VALUE;
ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request,
customContentTypeSupport, representationType);
ep.readPropertyValue(request, response, uriInfo, requestedContentType);
selectProcessor(PrimitiveProcessor.class)
.readPrimitiveAsValue(request, response, uriInfo, requestedContentType);
} else {
throw new ODataHandlerException("Media Entity is not implemented.",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
} else {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
break;
default:
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);

View File

@ -25,10 +25,12 @@ import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataHttpHandler;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.edm.provider.EdmProvider;
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.core.serializer.ODataXmlSerializerImpl;
import org.apache.olingo.server.core.serializer.FixedFormatSerializerImpl;
import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer;
import org.apache.olingo.server.core.serializer.xml.ODataXmlSerializerImpl;
import java.util.List;
@ -54,6 +56,11 @@ public class ODataImpl extends OData {
return serializer;
}
@Override
public FixedFormatSerializer createFixedFormatSerializer() throws SerializerException {
return new FixedFormatSerializerImpl();
}
@Override
public ODataHttpHandler createHandler(final ServiceMetadata edm) {
return new ODataHttpHandlerImpl(this, edm);

View File

@ -0,0 +1,59 @@
/*
* 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.server.core.serializer;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
import org.apache.olingo.server.api.serializer.PrimitiveValueSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
public class FixedFormatSerializerImpl implements FixedFormatSerializer {
@Override
public InputStream binary(final byte[] binary) throws SerializerException {
return new ByteArrayInputStream(binary);
}
@Override
public InputStream count(final Integer count) throws SerializerException {
return new ByteArrayInputStream(count.toString().getBytes());
}
@Override
public InputStream primitiveValue(final EdmPrimitiveType type, final Object value,
final PrimitiveValueSerializerOptions options) throws SerializerException {
try {
final String result = type.valueToString(value,
options.isNullable(), options.getMaxLength(),
options.getPrecision(), options.getScale(), options.isUnicode());
return new ByteArrayInputStream(result.getBytes("UTF-8"));
} catch (final EdmPrimitiveTypeException e) {
throw new SerializerException("Error in primitive-value formatting.", e,
SerializerException.MessageKeys.WRONG_PRIMITIVE_VALUE,
type.getFullQualifiedName().getFullQualifiedNameAsString(), value.toString());
} catch (final UnsupportedEncodingException e) {
throw new SerializerException("Encoding exception.", e, SerializerException.MessageKeys.IO_EXCEPTION);
}
}
}

View File

@ -20,6 +20,7 @@ package org.apache.olingo.server.core.serializer.json;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@ -28,24 +29,28 @@ import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.Linked;
import org.apache.olingo.commons.api.data.LinkedComplexValue;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@ -129,14 +134,14 @@ public class ODataJsonSerializer implements ODataSerializer {
}
@Override
public InputStream entitySet(final EdmEntitySet edmEntitySet, final EntitySet entitySet,
final ODataSerializerOptions options) throws SerializerException {
public InputStream entityCollection(final EdmEntityType entityType, final EntitySet entitySet,
final EntityCollectionSerializerOptions options) throws SerializerException {
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
json.writeStartObject();
final ContextURL contextURL = checkContextURL(options);
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
if (contextURL != null) {
json.writeStringField(Constants.JSON_CONTEXT,
ContextURLBuilder.create(contextURL).toASCIIString());
@ -147,7 +152,7 @@ public class ODataJsonSerializer implements ODataSerializer {
json.writeNumberField(Constants.JSON_COUNT, entitySet.getCount());
}
json.writeFieldName(Constants.VALUE);
writeEntitySet(edmEntitySet.getEntityType(), entitySet,
writeEntitySet(entityType, entitySet,
options == null ? null : options.getExpand(), options == null ? null : options.getSelect(), json);
if (entitySet.getNext() != null) {
json.writeStringField(Constants.JSON_NEXT_LINK, entitySet.getNext().toASCIIString());
@ -161,13 +166,13 @@ public class ODataJsonSerializer implements ODataSerializer {
}
@Override
public InputStream entity(final EdmEntitySet edmEntitySet, final Entity entity,
final ODataSerializerOptions options) throws SerializerException {
final ContextURL contextURL = checkContextURL(options);
public InputStream entity(final EdmEntityType entityType, final Entity entity,
final EntitySerializerOptions options) throws SerializerException {
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
writeEntity(edmEntitySet.getEntityType(), entity, contextURL,
writeEntity(entityType, entity, contextURL,
options == null ? null : options.getExpand(), options == null ? null : options.getSelect(), json);
json.close();
} catch (final IOException e) {
@ -177,16 +182,13 @@ public class ODataJsonSerializer implements ODataSerializer {
return buffer.getInputStream();
}
private ContextURL checkContextURL(final ODataSerializerOptions options) throws SerializerException {
private ContextURL checkContextURL(final ContextURL contextURL) throws SerializerException {
if (format == ODataFormat.JSON_NO_METADATA) {
return null;
} else {
final ContextURL contextURL = options == null ? null : options.getContextURL();
if (contextURL == null) {
throw new SerializerException("ContextURL null!", SerializerException.MessageKeys.NO_CONTEXT_URL);
}
return contextURL;
} else if (contextURL == null) {
throw new SerializerException("ContextURL null!", SerializerException.MessageKeys.NO_CONTEXT_URL);
}
return contextURL;
}
protected void writeEntitySet(final EdmEntityType entityType, final EntitySet entitySet,
@ -219,20 +221,20 @@ public class ODataJsonSerializer implements ODataSerializer {
}
}
}
writeProperties(entityType, entity, select, json);
writeProperties(entityType, entity.getProperties(), select, json);
writeNavigationProperties(entityType, entity, expand, json);
json.writeEndObject();
}
protected void writeProperties(final EdmEntityType entityType, final Entity entity, final SelectOption select,
JsonGenerator json) throws IOException, SerializerException {
protected void writeProperties(final EdmStructuredType type, final List<Property> properties,
final SelectOption select, JsonGenerator json) throws IOException, SerializerException {
final boolean all = ExpandSelectHelper.isAll(select);
final Set<String> selected = all ? null :
ExpandSelectHelper.getSelectedPropertyNames(select.getSelectItems());
for (final String propertyName : entityType.getPropertyNames()) {
for (final String propertyName : type.getPropertyNames()) {
if (all || selected.contains(propertyName)) {
final EdmProperty edmProperty = entityType.getStructuralProperty(propertyName);
final Property property = entity.getProperty(propertyName);
final EdmProperty edmProperty = type.getStructuralProperty(propertyName);
final Property property = findProperty(propertyName, properties);
final Set<List<String>> selectedPaths = all || edmProperty.isPrimitive() ? null :
ExpandSelectHelper.getSelectedPaths(select.getSelectItems(), propertyName);
writeProperty(edmProperty, property, selectedPaths, json);
@ -240,16 +242,16 @@ public class ODataJsonSerializer implements ODataSerializer {
}
}
protected void writeNavigationProperties(final EdmEntityType entityType, final Entity entity,
protected void writeNavigationProperties(final EdmStructuredType type, final Linked linked,
final ExpandOption expand, final JsonGenerator json) throws SerializerException, IOException {
if (ExpandSelectHelper.hasExpand(expand)) {
final boolean expandAll = ExpandSelectHelper.isExpandAll(expand);
final Set<String> expanded = expandAll ? null :
ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems());
for (final String propertyName : entityType.getNavigationPropertyNames()) {
for (final String propertyName : type.getNavigationPropertyNames()) {
if (expandAll || expanded.contains(propertyName)) {
final EdmNavigationProperty property = entityType.getNavigationProperty(propertyName);
final Link navigationLink = entity.getNavigationLink(property.getName());
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
final Link navigationLink = linked.getNavigationLink(property.getName());
final ExpandItem innerOptions = expandAll ? null :
ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
if (innerOptions != null && (innerOptions.isRef() || innerOptions.getLevelsOption() != null)) {
@ -304,14 +306,25 @@ public class ODataJsonSerializer implements ODataSerializer {
final Property property, final Set<List<String>> selectedPaths,
final JsonGenerator json) throws IOException, SerializerException {
try {
if (edmProperty.isCollection()) {
writeCollection(edmProperty, property, selectedPaths, json);
} else if (edmProperty.isPrimitive()) {
writePrimitive(edmProperty, property, json);
if (edmProperty.isPrimitive()) {
if (edmProperty.isCollection()) {
writePrimitiveCollection((EdmPrimitiveType) edmProperty.getType(), property,
edmProperty.isNullable(), edmProperty.getMaxLength(),
edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(),
json);
} else {
writePrimitive((EdmPrimitiveType) edmProperty.getType(), property,
edmProperty.isNullable(), edmProperty.getMaxLength(),
edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(),
json);
}
} else if (edmProperty.isCollection()) {
writeComplexCollection((EdmComplexType) edmProperty.getType(), property, selectedPaths, json);
} else if (property.isLinkedComplex()) {
writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), selectedPaths, json);
writeComplexValue((EdmComplexType) edmProperty.getType(), property.asLinkedComplex().getValue(),
selectedPaths, json);
} else if (property.isComplex()) {
writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
writeComplexValue((EdmComplexType) edmProperty.getType(), property.asComplex(), selectedPaths, json);
} else {
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
@ -323,56 +336,75 @@ public class ODataJsonSerializer implements ODataSerializer {
}
}
private void writeCollection(final EdmProperty edmProperty, final Property property,
final Set<List<String>> selectedPaths, JsonGenerator json)
throws IOException, EdmPrimitiveTypeException, SerializerException {
private void writePrimitiveCollection(final EdmPrimitiveType type, final Property property,
final Boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
final Boolean isUnicode,
JsonGenerator json) throws IOException, EdmPrimitiveTypeException, SerializerException {
json.writeStartArray();
for (Object value : property.asCollection()) {
switch (property.getValueType()) {
case COLLECTION_PRIMITIVE:
writePrimitiveValue(edmProperty, value, json);
writePrimitiveValue(type, value, isNullable, maxLength, precision, scale, isUnicode, json);
break;
case COLLECTION_GEOSPATIAL:
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
case COLLECTION_ENUM:
json.writeString(value.toString());
break;
case COLLECTION_LINKED_COMPLEX:
writeComplexValue(edmProperty, ((LinkedComplexValue) value).getValue(), selectedPaths, json);
break;
case COLLECTION_COMPLEX:
writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
break;
default:
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
}
}
json.writeEndArray();
}
private void writePrimitive(EdmProperty edmProperty, Property property, JsonGenerator json)
private void writeComplexCollection(final EdmComplexType type, final Property property,
final Set<List<String>> selectedPaths, JsonGenerator json)
throws IOException, EdmPrimitiveTypeException, SerializerException {
json.writeStartArray();
for (Object value : property.asCollection()) {
switch (property.getValueType()) {
case COLLECTION_LINKED_COMPLEX:
writeComplexValue(type, ((LinkedComplexValue) value).getValue(), selectedPaths, json);
break;
case COLLECTION_COMPLEX:
writeComplexValue(type, property.asComplex(), selectedPaths, json);
break;
default:
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
}
}
json.writeEndArray();
}
private void writePrimitive(final EdmPrimitiveType type, final Property property,
final Boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
final Boolean isUnicode, JsonGenerator json)
throws EdmPrimitiveTypeException, IOException, SerializerException {
if (property.isPrimitive()) {
writePrimitiveValue(edmProperty, property.asPrimitive(), json);
writePrimitiveValue(type, property.asPrimitive(),
isNullable, maxLength, precision, scale, isUnicode, json);
} else if (property.isGeospatial()) {
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
} else if (property.isEnum()) {
writePrimitiveValue(edmProperty, property.asEnum(), json);
writePrimitiveValue(type, property.asEnum(),
isNullable, maxLength, precision, scale, isUnicode, json);
} else {
throw new SerializerException("Inconsistent property type!",
SerializerException.MessageKeys.INCONSISTENT_PROPERTY_TYPE, edmProperty.getName());
SerializerException.MessageKeys.INCONSISTENT_PROPERTY_TYPE, property.getName());
}
}
protected void writePrimitiveValue(final EdmProperty edmProperty, final Object primitiveValue,
protected void writePrimitiveValue(final EdmPrimitiveType type, final Object primitiveValue,
final Boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
final Boolean isUnicode,
final JsonGenerator json) throws EdmPrimitiveTypeException, IOException {
final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
final String value = type.valueToString(primitiveValue,
edmProperty.isNullable(), edmProperty.getMaxLength(),
edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode());
isNullable, maxLength, precision, scale, isUnicode);
if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)) {
json.writeBoolean(Boolean.parseBoolean(value));
} else if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Byte)
@ -389,18 +421,10 @@ public class ODataJsonSerializer implements ODataSerializer {
}
}
protected void writeComplexValue(final EdmProperty edmProperty, final List<Property> properties,
protected void writeComplexValue(final EdmComplexType type, final List<Property> properties,
final Set<List<String>> selectedPaths, JsonGenerator json)
throws IOException, EdmPrimitiveTypeException, SerializerException {
json.writeStartObject();
writePropertyValues(edmProperty, properties, selectedPaths, json);
json.writeEndObject();
}
private void writePropertyValues(final EdmProperty edmProperty,
final List<Property> properties, final Set<List<String>> selectedPaths,
JsonGenerator json) throws IOException, SerializerException {
final EdmComplexType type = (EdmComplexType) edmProperty.getType();
for (final String propertyName : type.getPropertyNames()) {
final Property property = findProperty(propertyName, properties);
if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) {
@ -409,6 +433,7 @@ public class ODataJsonSerializer implements ODataSerializer {
json);
}
}
json.writeEndObject();
}
private Property findProperty(final String propertyName, final List<Property> properties) {
@ -421,9 +446,9 @@ public class ODataJsonSerializer implements ODataSerializer {
}
@Override
public InputStream entityProperty(final EdmProperty edmProperty, final Property property,
final ODataSerializerOptions options) throws SerializerException {
final ContextURL contextURL = checkContextURL(options);
public InputStream primitive(final EdmPrimitiveType type, final Property property,
final PrimitiveSerializerOptions options) throws SerializerException {
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
@ -431,15 +456,45 @@ public class ODataJsonSerializer implements ODataSerializer {
if (contextURL != null) {
json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
}
if (property.isPrimitive() && property.isNull()) {
if (property.isNull()) {
throw new SerializerException("Property value can not be null.", SerializerException.MessageKeys.NULL_INPUT);
} else if (property.isComplex() && !property.isNull()) {
writePropertyValues(edmProperty, property.asComplex(), null, json);
} else if (property.isLinkedComplex() && !property.isNull()) {
writePropertyValues(edmProperty, property.asLinkedComplex().getValue(), null, json);
} else {
json.writeFieldName(Constants.VALUE);
writePropertyValue(edmProperty, property, null, json);
writePrimitive(type, property,
options.isNullable(), options.getMaxLength(), options.getPrecision(), options.getScale(),
options.isUnicode(),
json);
}
json.writeEndObject();
json.close();
} catch (final IOException e) {
throw new SerializerException("An I/O exception occurred.", e,
SerializerException.MessageKeys.IO_EXCEPTION);
} catch (final EdmPrimitiveTypeException e) {
throw new SerializerException("Wrong value for property!", e,
SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
property.getName(), property.getValue().toString());
}
return buffer.getInputStream();
}
@Override
public InputStream complex(final EdmComplexType type, final Property property,
final ComplexSerializerOptions options) throws SerializerException {
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
json.writeStartObject();
if (contextURL != null) {
json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
}
final List<Property> values = property.isNull() ? Collections.<Property> emptyList() :
property.isComplex() ? property.asComplex() : property.asLinkedComplex().getValue();
writeProperties(type, values, options == null ? null : options.getSelect(), json);
if (!property.isNull() && property.isLinkedComplex()) {
writeNavigationProperties(type, property.asLinkedComplex(),
options == null ? null : options.getExpand(), json);
}
json.writeEndObject();
json.close();
@ -451,9 +506,64 @@ public class ODataJsonSerializer implements ODataSerializer {
}
@Override
public String buildContextURLSelectList(final EdmEntitySet edmEntitySet,
public InputStream primitiveCollection(final EdmPrimitiveType type, final Property property,
final PrimitiveSerializerOptions options) throws SerializerException {
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
json.writeStartObject();
if (contextURL != null) {
json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
}
json.writeFieldName(Constants.VALUE);
writePrimitiveCollection(type, property,
options.isNullable(), options.getMaxLength(), options.getPrecision(), options.getScale(),
options.isUnicode(),
json);
json.writeEndObject();
json.close();
} catch (final IOException e) {
throw new SerializerException("An I/O exception occurred.", e,
SerializerException.MessageKeys.IO_EXCEPTION);
} catch (final EdmPrimitiveTypeException e) {
throw new SerializerException("Wrong value for property!", e,
SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
property.getName(), property.getValue().toString());
}
return buffer.getInputStream();
}
@Override
public InputStream complexCollection(final EdmComplexType type, final Property property,
final ComplexSerializerOptions options) throws SerializerException {
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
json.writeStartObject();
if (contextURL != null) {
json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
}
json.writeFieldName(Constants.VALUE);
writeComplexCollection(type, property, null, json);
json.writeEndObject();
json.close();
} catch (final IOException e) {
throw new SerializerException("An I/O exception occurred.", e,
SerializerException.MessageKeys.IO_EXCEPTION);
} catch (final EdmPrimitiveTypeException e) {
throw new SerializerException("Wrong value for property!", e,
SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
property.getName(), property.getValue().toString());
}
return buffer.getInputStream();
}
@Override
public String buildContextURLSelectList(final EdmStructuredType type,
final ExpandOption expand, final SelectOption select) throws SerializerException {
return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select);
return ContextURLHelper.buildSelectList(type, expand, select);
}
@Override

View File

@ -56,12 +56,12 @@ public final class ContextURLBuilder {
if (contextURL.getKeyPath() != null) {
result.append('(').append(contextURL.getKeyPath()).append(')');
}
if (contextURL.getSelectList() != null) {
result.append('(').append(contextURL.getSelectList()).append(')');
}
if (contextURL.getNavOrPropertyPath() != null) {
result.append('/').append(contextURL.getNavOrPropertyPath());
}
if (contextURL.getSelectList() != null) {
result.append('(').append(contextURL.getSelectList()).append(')');
}
if (contextURL.isReference()) {
if (contextURL.getEntitySetOrSingletonOrType() != null) {
throw new IllegalArgumentException("ContextURL: $ref with Entity Set");

View File

@ -24,8 +24,8 @@ import java.util.List;
import java.util.Set;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.core.Encoder;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriParameter;
@ -39,37 +39,37 @@ public final class ContextURLHelper {
/** Builds a list of selected Properties for the ContextURL,
* taking care to preserve the order as defined in the EDM;
* returns NULL if no selection has taken place.
* @param entityType the Entity Type
* @param expand the Expand option (from the URL's $expand query option)
* @param select the Select option (from the URL's $select query option)
* @param type the structured type
* @param expand the Expand option (from the URL's $expand query option)
* @param select the Select option (from the URL's $select query option)
* @return a select-list String
* @throws SerializerException if an unsupported feature is used
*/
public static String buildSelectList(final EdmEntityType entityType,
public static String buildSelectList(final EdmStructuredType type,
final ExpandOption expand, final SelectOption select) throws SerializerException {
StringBuilder result = new StringBuilder();
if (ExpandSelectHelper.hasSelect(select)) {
handleSelect(entityType, select, result);
handleSelect(type, select, result);
}
if (ExpandSelectHelper.hasExpand(expand) && !ExpandSelectHelper.isExpandAll(expand)) {
handleExpand(entityType, expand, result);
handleExpand(type, expand, result);
}
return result.length() == 0 ? null : result.toString();
}
private static void handleSelect(final EdmEntityType entityType, final SelectOption select, StringBuilder result) {
private static void handleSelect(final EdmStructuredType type, final SelectOption select, StringBuilder result) {
if (ExpandSelectHelper.isAll(select)) {
result.append('*');
} else {
final List<SelectItem> selectItems = select.getSelectItems();
final Set<String> selectedPropertyNames = ExpandSelectHelper.getSelectedPropertyNames(selectItems);
for (final String propertyName : entityType.getPropertyNames()) {
for (final String propertyName : type.getPropertyNames()) {
if (selectedPropertyNames.contains(propertyName)) {
if (result.length() > 0) {
result.append(',');
}
final EdmProperty edmProperty = (EdmProperty) entityType.getProperty(propertyName);
final EdmProperty edmProperty = type.getStructuralProperty(propertyName);
final Set<List<String>> selectedPaths = ExpandSelectHelper.getSelectedPaths(selectItems, propertyName);
if (selectedPaths == null) {
result.append(Encoder.encode(propertyName));
@ -98,16 +98,16 @@ public final class ContextURLHelper {
}
}
private static void handleExpand(final EdmEntityType entityType, final ExpandOption expand, StringBuilder result)
private static void handleExpand(final EdmStructuredType type, final ExpandOption expand, StringBuilder result)
throws SerializerException {
final Set<String> expandedPropertyNames = ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems());
for (final String propertyName : entityType.getNavigationPropertyNames()) {
for (final String propertyName : type.getNavigationPropertyNames()) {
if (expandedPropertyNames.contains(propertyName)) {
final ExpandItem expandItem = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
if (ExpandSelectHelper.hasExpand(expandItem.getExpandOption())
&& !ExpandSelectHelper.isExpandAll(expandItem.getExpandOption())
|| ExpandSelectHelper.hasSelect(expandItem.getSelectOption())) {
final String innerSelectList = buildSelectList(entityType.getNavigationProperty(propertyName).getType(),
final String innerSelectList = buildSelectList(type.getNavigationProperty(propertyName).getType(),
expandItem.getExpandOption(), expandItem.getSelectOption());
if (innerSelectList != null) {
if (result.length() > 0) {

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.server.core.serializer;
package org.apache.olingo.server.core.serializer.xml;
import java.io.InputStream;
import java.util.List;
@ -29,24 +29,31 @@ import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
import org.apache.olingo.server.core.serializer.utils.ContextURLHelper;
import org.apache.olingo.server.core.serializer.xml.MetadataDocumentXmlSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ODataXmlSerializerImpl implements ODataSerializer {
/** The default character set is UTF-8. */
public static final String DEFAULT_CHARSET = "UTF-8";
private static final Logger log = LoggerFactory.getLogger(ODataXmlSerializerImpl.class);
@Override
@ -87,15 +94,15 @@ public class ODataXmlSerializerImpl implements ODataSerializer {
}
@Override
public InputStream entity(final EdmEntitySet edmEntitySet, final Entity entity,
final ODataSerializerOptions options) throws SerializerException {
public InputStream entity(final EdmEntityType entityType, final Entity entity,
final EntitySerializerOptions options) throws SerializerException {
throw new SerializerException("Entity serialization not implemented for XML format",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
@Override
public InputStream entitySet(final EdmEntitySet edmEntitySet, final EntitySet entitySet,
final ODataSerializerOptions options) throws SerializerException {
public InputStream entityCollection(final EdmEntityType entityType, final EntitySet entitySet,
final EntityCollectionSerializerOptions options) throws SerializerException {
throw new SerializerException("Entityset serialization not implemented for XML format",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
@ -107,16 +114,37 @@ public class ODataXmlSerializerImpl implements ODataSerializer {
}
@Override
public InputStream entityProperty(EdmProperty edmProperty, Property property,
ODataSerializerOptions options) throws SerializerException{
throw new SerializerException("error serialization not implemented for XML format",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
public InputStream primitive(final EdmPrimitiveType type, final Property property,
final PrimitiveSerializerOptions options) throws SerializerException {
throw new SerializerException("Serialization not implemented for XML format.",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
@Override
public String buildContextURLSelectList(final EdmEntitySet edmEntitySet,
public InputStream complex(final EdmComplexType type, final Property property,
final ComplexSerializerOptions options) throws SerializerException {
throw new SerializerException("Serialization not implemented for XML format.",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
@Override
public InputStream primitiveCollection(final EdmPrimitiveType type, final Property property,
final PrimitiveSerializerOptions options) throws SerializerException {
throw new SerializerException("Serialization not implemented for XML format.",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
@Override
public InputStream complexCollection(final EdmComplexType type, final Property property,
final ComplexSerializerOptions options) throws SerializerException {
throw new SerializerException("Serialization not implemented for XML format.",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
@Override
public String buildContextURLSelectList(final EdmStructuredType type,
final ExpandOption expand, final SelectOption select) throws SerializerException {
return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select);
return ContextURLHelper.buildSelectList(type, expand, select);
}
@Override

View File

@ -84,7 +84,6 @@ public class UriValidator {
/* PUT 0 */ { false , false , false , false, false , false , false , false , false , false , false , false },
/* DELETE 0 */ { false , false , false , false, false , false, false , false, false , false , false, false },
/* PATCH 0 */ { false , false , false , false, false , false , false , false , false , false , false , false },
/* MERGE 0 */ { false , false , false , false, false , false , false , false , false , false , false , false },
};
//CHECKSTYLE:ON
@ -154,8 +153,7 @@ public class UriValidator {
POST(1),
PUT(2),
DELETE(3),
MERGE(4),
PATCH(5);
PATCH(4);
private int idx;
@ -602,9 +600,6 @@ public class UriValidator {
case PATCH:
idx = RowIndexForHttpMethod.PATCH;
break;
case MERGE:
idx = RowIndexForHttpMethod.MERGE;
break;
default:
throw new UriValidationException("HTTP method not supported: " + httpMethod,
UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD, httpMethod.toString());

View File

@ -94,6 +94,7 @@ SerializerException.UNSUPPORTED_PROPERTY_TYPE=The type of the property '%1$s' is
SerializerException.INCONSISTENT_PROPERTY_TYPE=An inconsistency has been detected in the type definition of property '%1$s'.
SerializerException.MISSING_PROPERTY=The non-nullable property '%1$s' is missing.
SerializerException.WRONG_PROPERTY_VALUE=The value '%2$s' is not valid for property '%1$s'.
SerializerException.WRONG_PRIMITIVE_VALUE=The value '%2$s' is not valid for the primitive type '%1$s' and the given facets.
BatchException.INVALID_BOUNDARY=Invalid boundary at line '%1$s'.
BatchException.INVALID_CHANGESET_METHOD=Invalid method: a ChangeSet cannot contain retrieve requests at line '%1$s'.

View File

@ -38,7 +38,6 @@ public class ODataHttpHandlerImplTest {
{ "GET", null, null, "GET" },
{ "GET", "xxx", "yyy", "GET" },
{ "PUT", "xxx", "yyy", "PUT" },
{ "MERGE", "xxx", "yyy", "MERGE" },
{ "DELETE", "xxx", "yyy", "DELETE" },
{ "PATCH", "xxx", "yyy", "PATCH" },
@ -47,7 +46,7 @@ public class ODataHttpHandlerImplTest {
{ "POST", null, "PATCH", "PATCH" },
{ "POST", "GET", null, "GET" },
{ "POST", "MERGE", null, "MERGE" },
{ "POST", "PATCH", null, "PATCH" },
{ "POST", "GET", "GET", "GET" },
};
@ -71,7 +70,7 @@ public class ODataHttpHandlerImplTest {
public void extractMethodFail() throws Exception {
String[][] mm = {
{ "POST", "bla", null },
{ "POST", "MERGE", "PATCH" },
{ "POST", "PUT", "PATCH" },
{ "OPTIONS", null, null },
{ "HEAD", null, null },
};

View File

@ -0,0 +1,57 @@
/*
* 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.server.core.serializer;
import static org.junit.Assert.assertEquals;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
import org.apache.olingo.server.api.serializer.PrimitiveValueSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.junit.Test;
public class FixedFormatSerializerTest {
private final FixedFormatSerializer serializer;
public FixedFormatSerializerTest() throws SerializerException {
serializer = OData.newInstance().createFixedFormatSerializer();
}
@Test
public void binary() throws Exception {
assertEquals("ABC", IOUtils.toString(serializer.binary(new byte [] { 0x41, 0x42, 0x43 })));
}
@Test
public void count() throws Exception {
assertEquals("42", IOUtils.toString(serializer.count(42)));
}
@Test
public void primitiveValue() throws Exception {
final EdmPrimitiveType type = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int32);
assertEquals("42", IOUtils.toString(serializer.primitiveValue(type, 42,
PrimitiveValueSerializerOptions.with().nullable(true).build())));
}
}

View File

@ -119,9 +119,10 @@ public class ContextURLBuilderTest {
contextURL = ContextURL.with().serviceRoot(URI.create("http://host/service/"))
.entitySet(entitySet)
.keyPath("one=1,two='two'")
.navOrPropertyPath("Name")
.navOrPropertyPath("ComplexName")
.selectList("Part1")
.build();
assertEquals("http://host/service/$metadata#Customers(one=1,two='two')/Name",
assertEquals("http://host/service/$metadata#Customers(one=1,two='two')/ComplexName(Part1)",
ContextURLBuilder.create(contextURL).toASCIIString());
}

View File

@ -24,7 +24,8 @@ import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
import org.apache.olingo.server.tecsvc.data.DataProvider;
import org.apache.olingo.server.tecsvc.processor.TechnicalProcessor;
import org.apache.olingo.server.tecsvc.processor.TechnicalEntityProcessor;
import org.apache.olingo.server.tecsvc.processor.TechnicalPrimitiveComplexProcessor;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -64,7 +65,8 @@ public class TechnicalServlet extends HttpServlet {
}
ODataHttpHandler handler = odata.createHandler(serviceMetadata);
handler.register(new TechnicalProcessor(dataProvider));
handler.register(new TechnicalEntityProcessor(dataProvider));
handler.register(new TechnicalPrimitiveComplexProcessor(dataProvider));
handler.process(req, resp);
} catch (RuntimeException e) {
LOG.error("Server Error", e);

View File

@ -0,0 +1,161 @@
/*
* 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.server.tecsvc.processor;
import java.util.List;
import java.util.Locale;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.ContextURL.Suffix;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.tecsvc.data.DataProvider;
/**
* Technical Processor for entity-related functionality.
*/
public class TechnicalEntityProcessor extends TechnicalProcessor
implements EntityCollectionProcessor, CountEntityCollectionProcessor, EntityProcessor {
public TechnicalEntityProcessor(final DataProvider dataProvider) {
super(dataProvider);
}
@Override
public void readEntityCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
if (uriInfo.asUriInfoResource().getUriResourceParts().size() > 1) {
throw new ODataApplicationException("Invalid resource type.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final EntitySet entitySet = readEntitySetInternal(edmEntitySet,
uriInfo.getCountOption() != null && uriInfo.getCountOption().getValue());
if (entitySet == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
response.setContent(serializer.entityCollection(edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, false, expand, select))
.count(uriInfo.getCountOption())
.expand(expand).select(select)
.build()));
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
}
}
@Override
public void countEntityCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
final List<UriResource> resourceParts = uriInfo.asUriInfoResource().getUriResourceParts();
final int pos = resourceParts.size() - 2;
if (pos > 0) {
throw new ODataApplicationException("Invalid resource type.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
final EntitySet entitySet =
readEntitySetInternal(((UriResourceEntitySet) resourceParts.get(pos)).getEntitySet(), true);
if (entitySet == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
response.setContent(odata.createFixedFormatSerializer().count(entitySet.getCount()));
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
}
}
@Override
public void readEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
if (uriInfo.asUriInfoResource().getUriResourceParts().size() > 1) {
throw new ODataApplicationException("Invalid resource type.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) uriInfo.getUriResourceParts().get(0);
final Entity entity = dataProvider.read(edmEntitySet, resourceEntitySet.getKeyPredicates());
if (entity == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
response.setContent(serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, true, expand, select))
.expand(expand).select(select)
.build()));
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
}
}
private EntitySet readEntitySetInternal(final EdmEntitySet edmEntitySet, final boolean withCount)
throws DataProvider.DataProviderException {
EntitySet entitySet = dataProvider.readAll(edmEntitySet);
// TODO: set count (correctly) and next link
if (withCount && entitySet.getCount() == null) {
entitySet.setCount(entitySet.getEntities().size());
}
return entitySet;
}
private ContextURL getContextUrl(final ODataSerializer serializer,
final EdmEntitySet entitySet, final boolean isSingleEntity,
final ExpandOption expand, final SelectOption select) throws SerializerException {
return ContextURL.with().entitySet(entitySet)
.selectList(serializer.buildContextURLSelectList(entitySet.getEntityType(), expand, select))
.suffix(isSingleEntity ? Suffix.ENTITY : null)
.build();
}
}

View File

@ -0,0 +1,243 @@
/*
* 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.server.tecsvc.processor;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
import org.apache.olingo.server.api.serializer.PrimitiveValueSerializerOptions;
import org.apache.olingo.server.api.serializer.RepresentationType;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.UriResourceProperty;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.tecsvc.data.DataProvider;
/**
* Technical Processor which provides functionality related to primitive and complex types and collections thereof.
*/
public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
implements PrimitiveProcessor, PrimitiveCollectionProcessor, ComplexProcessor, ComplexCollectionProcessor {
public TechnicalPrimitiveComplexProcessor(final DataProvider dataProvider) {
super(dataProvider);
}
@Override
public void readPrimitive(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
readProperty(response, uriInfo, contentType, RepresentationType.PRIMITIVE);
}
@Override
public void readPrimitiveCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
readProperty(response, uriInfo, contentType, RepresentationType.COLLECTION_PRIMITIVE);
}
@Override
public void readComplex(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
readProperty(response, uriInfo, contentType, RepresentationType.COMPLEX);
}
@Override
public void readComplexCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
readProperty(response, uriInfo, contentType, RepresentationType.COLLECTION_COMPLEX);
}
private void readProperty(ODataResponse response, final UriInfo uriInfo, final ContentType contentType,
final RepresentationType representationType) throws ODataApplicationException, SerializerException {
final UriInfoResource resource = uriInfo.asUriInfoResource();
validateOptions(resource);
validatePath(resource);
final List<UriResource> resourceParts = resource.getUriResourceParts();
final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) resourceParts.get(0);
final List<String> path = getPropertyPath(resourceParts);
final Property property = getPropertyData(resourceEntitySet, path);
if (property == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
if (property.getValue() == null) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
final EdmEntitySet edmEntitySet = getEdmEntitySet(resource);
final EdmProperty edmProperty = ((UriResourceProperty) resourceParts.get(path.size())).getProperty();
final ODataFormat format = ODataFormat.fromContentType(contentType);
ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
final ContextURL contextURL = format == ODataFormat.JSON_NO_METADATA ? null :
ContextURL.with().entitySet(edmEntitySet)
.keyPath(serializer.buildContextURLKeyPredicate(
((UriResourceEntitySet) resourceParts.get(0)).getKeyPredicates()))
.navOrPropertyPath(buildPropertyPath(path))
.selectList(edmProperty.isPrimitive() ? null :
serializer.buildContextURLSelectList((EdmStructuredType) edmProperty.getType(), expand, select))
.build();
switch (representationType) {
case PRIMITIVE:
response.setContent(serializer.primitive((EdmPrimitiveType) edmProperty.getType(), property,
PrimitiveSerializerOptions.with().contextURL(contextURL).facetsFrom(edmProperty).build()));
break;
case COMPLEX:
response.setContent(serializer.complex((EdmComplexType) edmProperty.getType(), property,
ComplexSerializerOptions.with().contextURL(contextURL)
.expand(expand).select(select)
.build()));
break;
case COLLECTION_PRIMITIVE:
response.setContent(serializer.primitiveCollection((EdmPrimitiveType) edmProperty.getType(), property,
PrimitiveSerializerOptions.with().contextURL(contextURL).facetsFrom(edmProperty).build()));
break;
case COLLECTION_COMPLEX:
response.setContent(serializer.complexCollection((EdmComplexType) edmProperty.getType(), property,
ComplexSerializerOptions.with().contextURL(contextURL)
.expand(expand).select(select)
.build()));
break;
default:
break;
}
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
}
}
}
private Property getPropertyData(final UriResourceEntitySet resourceEntitySet, final List<String> path)
throws ODataApplicationException {
final Entity entity = dataProvider.read(resourceEntitySet.getEntitySet(), resourceEntitySet.getKeyPredicates());
if (entity == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
Property property = entity.getProperty(path.get(0));
for (final String name : path.subList(1, path.size())) {
if (property != null && (property.isLinkedComplex() || property.isComplex())) {
final List<Property> complex = property.isLinkedComplex() ?
property.asLinkedComplex().getValue() : property.asComplex();
property = null;
for (final Property innerProperty : complex) {
if (innerProperty.getName().equals(name)) {
property = innerProperty;
break;
}
}
}
}
return property;
}
}
private List<String> getPropertyPath(final List<UriResource> path) {
List<String> result = new LinkedList<String>();
int index = 1;
while (index < path.size() && path.get(index) instanceof UriResourceProperty) {
result.add(((UriResourceProperty) path.get(index)).getProperty().getName());
index++;
}
return result;
}
private String buildPropertyPath(final List<String> path) {
StringBuilder result = new StringBuilder();
for (final String segment : path) {
result.append(result.length() == 0 ? "" : '/').append(segment);
}
return result.toString();
}
@Override
public void readPrimitiveAsValue(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
final UriInfoResource resource = uriInfo.asUriInfoResource();
validateOptions(resource);
validatePath(resource);
final List<UriResource> resourceParts = resource.getUriResourceParts();
final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) resourceParts.get(0);
final List<String> path = getPropertyPath(resourceParts);
final Property property = getPropertyData(resourceEntitySet, path);
if (property == null || property.getValue() == null) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
final EdmProperty edmProperty = ((UriResourceProperty) resourceParts.get(path.size())).getProperty();
final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
final FixedFormatSerializer serializer = odata.createFixedFormatSerializer();
response.setContent(type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
serializer.binary((byte[]) property.getValue()) :
serializer.primitiveValue(type, property.getValue(),
PrimitiveValueSerializerOptions.with().facetsFrom(edmProperty).build()));
response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
}
}
private void validatePath(final UriInfoResource uriInfo) throws ODataApplicationException {
final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
for (final UriResource segment : resourcePaths.subList(1, resourcePaths.size())) {
final UriResourceKind kind = segment.getKind();
if (kind != UriResourceKind.primitiveProperty
&& kind != UriResourceKind.complexProperty
&& kind != UriResourceKind.count
&& kind != UriResourceKind.value) {
throw new ODataApplicationException("Invalid resource type.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
}
}
}

View File

@ -18,67 +18,30 @@
*/
package org.apache.olingo.server.tecsvc.processor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.apache.olingo.commons.api.ODataRuntimeException;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.ContextURL.Suffix;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.batch.BatchException;
import org.apache.olingo.server.api.batch.BatchOperation;
import org.apache.olingo.server.api.batch.BatchRequestPart;
import org.apache.olingo.server.api.batch.ODataResponsePart;
import org.apache.olingo.server.api.processor.BatchProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.EntitySetProcessor;
import org.apache.olingo.server.api.processor.PropertyProcessor;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.UriResourceProperty;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.tecsvc.data.DataProvider;
/**
* Technical Processor which provides currently implemented processor functionality.
* Technical Processor base.
*/
public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor {
public abstract class TechnicalProcessor implements Processor {
private OData odata;
private DataProvider dataProvider;
protected OData odata;
protected DataProvider dataProvider;
public TechnicalProcessor(final DataProvider dataProvider) {
protected TechnicalProcessor(final DataProvider dataProvider) {
this.dataProvider = dataProvider;
}
@ -87,92 +50,23 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor,
this.odata = odata;
}
@Override
public void readEntitySet(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final EntitySet entitySet = readEntitySetInternal(edmEntitySet,
uriInfo.getCountOption() != null && uriInfo.getCountOption().getValue());
if (entitySet == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
response.setContent(serializer.entitySet(edmEntitySet, entitySet,
ODataSerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, false, expand, select, null, null))
.count(uriInfo.getCountOption())
.expand(expand).select(select)
.build()));
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
protected EdmEntitySet getEdmEntitySet(final UriInfoResource uriInfo) throws ODataApplicationException {
final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
// first must be entity set
if (!(resourcePaths.get(0) instanceof UriResourceEntitySet)) {
throw new ODataApplicationException("Invalid resource type.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
}
@Override
public void readEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet);
if (entity == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
response.setContent(serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, true, expand, select, null, null))
.count(uriInfo.getCountOption())
.expand(expand).select(select)
.build()));
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
final UriResourceEntitySet uriResource = (UriResourceEntitySet) resourcePaths.get(0);
if (uriResource.getTypeFilterOnCollection() != null || uriResource.getTypeFilterOnEntry() != null) {
throw new ODataApplicationException("Type filters are not supported.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
return uriResource.getEntitySet();
}
@Override
public void countEntitySet(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
throws ODataApplicationException, SerializerException {
final List<UriResource> resourceParts = uriInfo.asUriInfoResource().getUriResourceParts();
final int pos = resourceParts.size() - 2;
final EntitySet entitySet =
readEntitySetInternal(((UriResourceEntitySet) resourceParts.get(pos)).getEntitySet(), true);
if (entitySet == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
response.setContent(new ByteArrayInputStream(entitySet.getCount().toString().getBytes()));
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, HttpContentType.TEXT_PLAIN);
}
}
private EntitySet readEntitySetInternal(final EdmEntitySet edmEntitySet,
final boolean withCount) throws DataProvider.DataProviderException {
EntitySet entitySet = dataProvider.readAll(edmEntitySet);
// TODO: set count (correctly) and next link
if (withCount && entitySet.getCount() == null) {
entitySet.setCount(entitySet.getEntities().size());
}
return entitySet;
}
private Entity readEntityInternal(final UriInfoResource uriInfo, final EdmEntitySet entitySet)
throws DataProvider.DataProviderException {
final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) uriInfo.getUriResourceParts().get(0);
return dataProvider.read(entitySet, resourceEntitySet.getKeyPredicates());
}
private void validateOptions(final UriInfoResource uriInfo) throws ODataApplicationException {
protected void validateOptions(final UriInfoResource uriInfo) throws ODataApplicationException {
if (uriInfo.getCountOption() != null
|| !uriInfo.getCustomQueryOptions().isEmpty()
|| uriInfo.getFilterOption() != null
@ -186,151 +80,4 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor,
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
}
private EdmEntitySet getEdmEntitySet(final UriInfoResource uriInfo) throws ODataApplicationException {
final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
// first must be entity set
if (!(resourcePaths.get(0) instanceof UriResourceEntitySet)) {
throw new ODataApplicationException("Invalid resource type.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
List<UriResource> subResPaths = resourcePaths.subList(1, resourcePaths.size());
for (UriResource subResPath : subResPaths) {
UriResourceKind kind = subResPath.getKind();
if (kind != UriResourceKind.primitiveProperty
&& kind != UriResourceKind.complexProperty
&& kind != UriResourceKind.count
&& kind != UriResourceKind.value) {
throw new ODataApplicationException("Invalid resource type.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
}
final UriResourceEntitySet uriResource = (UriResourceEntitySet) resourcePaths.get(0);
if (uriResource.getTypeFilterOnCollection() != null || uriResource.getTypeFilterOnEntry() != null) {
throw new ODataApplicationException("Type filters are not supported.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
return uriResource.getEntitySet();
}
private ContextURL getContextUrl(final ODataSerializer serializer,
final EdmEntitySet entitySet, final boolean isSingleEntity,
final ExpandOption expand, final SelectOption select,
final List<UriParameter> keys, final String propertyPath) throws SerializerException {
return ContextURL.with().entitySet(entitySet)
.selectList(serializer.buildContextURLSelectList(entitySet, expand, select))
.suffix(isSingleEntity && propertyPath == null ? Suffix.ENTITY : null)
.keyPath(serializer.buildContextURLKeyPredicate(keys))
.navOrPropertyPath(propertyPath)
.build();
}
@Override
public void readProperty(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final List<UriResource> resourceParts = uriInfo.getUriResourceParts();
final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) resourceParts.get(0);
final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet);
if (entity == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
final List<String> path = getPropertyPath(resourceParts);
EdmProperty edmProperty = edmEntitySet.getEntityType().getStructuralProperty(path.get(0));
Property property = entity.getProperty(path.get(0));
for (final String name : path.subList(1, path.size())) {
if (property != null && (property.isLinkedComplex() || property.isComplex())) {
edmProperty = ((EdmComplexType) edmProperty.getType()).getStructuralProperty(name);
final List<Property> complex = property.isLinkedComplex() ?
property.asLinkedComplex().getValue() :
property.asComplex();
property = null;
for (final Property innerProperty : complex) {
if (innerProperty.getName().equals(name)) {
property = innerProperty;
break;
}
}
}
}
if (property == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
if (property.getValue() == null) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
final ODataFormat format = ODataFormat.fromContentType(contentType);
ODataSerializer serializer = odata.createSerializer(format);
response.setContent(serializer.entityProperty(edmProperty, property,
ODataSerializerOptions.with().contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, true, null, null,
resourceEntitySet.getKeyPredicates(), buildPropertyPath(path)))
.build()));
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
}
}
}
}
private List<String> getPropertyPath(final List<UriResource> path) {
List<String> result = new LinkedList<String>();
int index = path.size();
while (path.get(--index) instanceof UriResourceProperty) {
result.add(0, ((UriResourceProperty) path.get(index)).getProperty().getName());
}
return result;
}
private String buildPropertyPath(final List<String> path) {
StringBuilder result = new StringBuilder();
for (final String segment : path) {
result.append(result.length() == 0 ? "" : '/').append(segment);
}
return result.toString();
}
@Override
public void readPropertyValue(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet);
if (entity == null) {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
} else {
final UriResourceProperty uriProperty =
(UriResourceProperty) uriInfo.getUriResourceParts().get(uriInfo.getUriResourceParts().size() - 2);
final EdmProperty edmProperty = uriProperty.getProperty();
final Property property = entity.getProperty(edmProperty.getName());
if (property == null || property.getValue() == null) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary)) {
response.setContent(new ByteArrayInputStream((byte[]) property.getValue()));
} else {
try {
final String value = type.valueToString(property.getValue(),
edmProperty.isNullable(), edmProperty.getMaxLength(),
edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode());
response.setContent(new ByteArrayInputStream(value.getBytes("UTF-8")));
} catch (final EdmPrimitiveTypeException e) {
throw new ODataApplicationException("Error in value formatting.",
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT, e);
} catch (final UnsupportedEncodingException e) {
throw new ODataApplicationException("Encoding exception.",
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT, e);
}
}
response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
}
}
}
}

View File

@ -1,210 +0,0 @@
/*
* 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.server.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import java.util.Collections;
import java.util.Locale;
import org.apache.olingo.commons.api.ODataException;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.edm.provider.EdmProvider;
import org.apache.olingo.server.api.edm.provider.EntitySet;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.processor.MetadataProcessor;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
import org.junit.Before;
import org.junit.Test;
public class ODataHandlerExceptionHandlingTest {
private ODataHandler handler;
@Before
public void before() {
OData odata = OData.newInstance();
ServiceMetadata metadata = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference>emptyList());
handler = new ODataHandler(odata, metadata);
}
@Test
public void wrongHttpMethodForMetadataDocument() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.POST);
request.setRawODataPath("$metadata");
ODataResponse response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.PUT);
request.setRawODataPath("$metadata");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.PATCH);
request.setRawODataPath("$metadata");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.MERGE);
request.setRawODataPath("$metadata");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.DELETE);
request.setRawODataPath("$metadata");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
}
@Test
public void wrongHttpMethodForServiceDocument() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.POST);
request.setRawODataPath("");
ODataResponse response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.PUT);
request.setRawODataPath("");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.PATCH);
request.setRawODataPath("");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.MERGE);
request.setRawODataPath("");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
request = new ODataRequest();
request.setMethod(HttpMethod.DELETE);
request.setRawODataPath("");
response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
}
@Test
public void testUriParserExceptionResultsInRightResponseNotFound() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("NotFound");
ODataResponse response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.NOT_FOUND.getStatusCode(), response.getStatusCode());
}
@Test
public void testUriParserExceptionResultsInRightResponseBadRequest() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("ESAllPrim('122')");
ODataResponse response = handler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), response.getStatusCode());
}
@Test
public void testUriParserExceptionResultsInRightResponseEdmCause() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("EdmException");
OData odata = OData.newInstance();
ServiceMetadata serviceMetadata = odata.createServiceMetadata(new EdmProvider() {
public EntitySet getEntitySet(final FullQualifiedName entityContainer, final String entitySetName)
throws ODataException {
throw new ODataException("msg");
}
}, Collections.<EdmxReference>emptyList());
ODataHandler localHandler = new ODataHandler(odata, serviceMetadata);
ODataResponse response = localHandler.process(request);
assertNotNull(response);
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
}
@Test
public void testWithApplicationExceptionInProcessor() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
MetadataProcessor metadataProcessor = mock(MetadataProcessor.class);
doThrow(new ODataApplicationException("msg", 425, Locale.ENGLISH)).when(metadataProcessor).readMetadata(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
handler.register(metadataProcessor);
ODataResponse response = handler.process(request);
assertNotNull(response);
assertEquals(425, response.getStatusCode());
}
}

View File

@ -18,15 +18,22 @@
*/
package org.apache.olingo.server.core;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.commons.api.ODataException;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpContentType;
@ -34,311 +41,303 @@ import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.edm.provider.EdmProvider;
import org.apache.olingo.server.api.edm.provider.EntitySet;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.processor.EntitySetProcessor;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.MetadataProcessor;
import org.apache.olingo.server.api.processor.PropertyProcessor;
import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class ODataHandlerTest {
private ODataHandler handler;
@Before
public void before() {
OData odata = OData.newInstance();
ServiceMetadata metadata = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference>emptyList());
handler = new ODataHandler(odata, metadata);
}
private static final String BASE_URI = "http://localhost/odata";
@Test
public void testServiceDocumentNonDefault() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawBaseUri("http://localhost/odata");
request.setRawODataPath("/");
ServiceDocumentProcessor processor = mock(ServiceDocumentProcessor.class);
handler.register(processor);
ODataResponse response = handler.process(request);
assertNotNull(response);
public void serviceDocumentNonDefault() throws Exception {
final ServiceDocumentProcessor processor = mock(ServiceDocumentProcessor.class);
final ODataResponse response = dispatch(HttpMethod.GET, "/", processor);
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
verify(processor).readServiceDocument(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatchMethodNotAllowed(HttpMethod.POST, "/", processor);
dispatchMethodNotAllowed(HttpMethod.PUT, "/", processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, "/", processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, "/", processor);
}
@Test
public void testServiceDocumentDefault() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawBaseUri("http://localhost/odata");
request.setRawODataPath("/");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void serviceDocumentDefault() throws Exception {
final ODataResponse response = dispatch(HttpMethod.GET, "/", null);
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
String ct = response.getHeaders().get(HttpHeader.CONTENT_TYPE);
assertTrue(ct.contains("application/json"));
assertTrue(ct.contains("odata.metadata=minimal"));
assertThat(ct, containsString("application/json"));
assertThat(ct, containsString("odata.metadata=minimal"));
assertNotNull(response.getContent());
String doc = IOUtils.toString(response.getContent());
assertTrue(doc.contains("\"@odata.context\" : \"http://localhost/odata/$metadata\""));
assertTrue(doc.contains("\"value\" :"));
assertThat(doc, containsString("\"@odata.context\" : \"" + BASE_URI + "/$metadata\""));
assertThat(doc, containsString("\"value\" :"));
}
@Test
public void testServiceDocumentRedirect() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawBaseUri("http://localhost/odata");
request.setRawRequestUri("http://localhost/odata");
request.setRawODataPath("");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void serviceDocumentRedirect() throws Exception {
final ODataResponse response = dispatch(HttpMethod.GET, "", null);
assertEquals(HttpStatusCode.TEMPORARY_REDIRECT.getStatusCode(), response.getStatusCode());
assertEquals("http://localhost/odata/", response.getHeaders().get(HttpHeader.LOCATION));
assertEquals(BASE_URI + "/", response.getHeaders().get(HttpHeader.LOCATION));
}
@Test
public void testMetadataNonDefault() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
MetadataProcessor processor = mock(MetadataProcessor.class);
handler.register(processor);
ODataResponse response = handler.process(request);
assertNotNull(response);
public void metadataNonDefault() throws Exception {
final MetadataProcessor processor = mock(MetadataProcessor.class);
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", processor);
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
verify(processor).readMetadata(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatchMethodNotAllowed(HttpMethod.POST, "$metadata", processor);
dispatchMethodNotAllowed(HttpMethod.PUT, "$metadata", processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, "$metadata", processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, "$metadata", processor);
}
@Test
public void testMetadataDefault() throws Exception {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void metadataDefault() throws Exception {
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", null);
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
assertEquals(HttpContentType.APPLICATION_XML, response.getHeaders().get(HttpHeader.CONTENT_TYPE));
assertNotNull(response.getContent());
String doc = IOUtils.toString(response.getContent());
assertTrue(doc.contains("<edmx:Edmx Version=\"4.0\""));
assertThat(IOUtils.toString(response.getContent()),
containsString("<edmx:Edmx Version=\"4.0\""));
}
@Test
public void testMaxVersionNone() {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void maxVersionNone() {
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", null);
assertEquals(ODataServiceVersion.V40.toString(), response.getHeaders().get(HttpHeader.ODATA_VERSION));
}
@Test
public void testMaxVersionSupported() {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
request.addHeader(HttpHeader.ODATA_MAX_VERSION, Arrays.asList(ODataServiceVersion.V40.toString()));
ODataResponse response = handler.process(request);
assertNotNull(response);
public void maxVersionSupported() {
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", null,
HttpHeader.ODATA_MAX_VERSION, ODataServiceVersion.V40.toString(), null);
assertEquals(ODataServiceVersion.V40.toString(), response.getHeaders().get(HttpHeader.ODATA_VERSION));
}
@Test
public void testMaxVersionNotSupported() {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
request.addHeader(HttpHeader.ODATA_MAX_VERSION, Arrays.asList(ODataServiceVersion.V30.toString()));
ODataResponse response = handler.process(request);
assertNotNull(response);
public void maxVersionNotSupported() {
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", null,
HttpHeader.ODATA_MAX_VERSION, ODataServiceVersion.V30.toString(), null);
assertEquals(ODataServiceVersion.V40.toString(), response.getHeaders().get(HttpHeader.ODATA_VERSION));
assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), response.getStatusCode());
}
@Test
public void testContentNegotiationSupported() {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
request.setRawQueryPath("$format=xml");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void contentNegotiationSupported() {
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", "$format=xml", null, null, null);
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
}
@Test
public void testContentNegotiationNotSupported() {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
request.setRawQueryPath("$format=not/Supported");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void contentNegotiationNotSupported() {
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", "$format=not/Supported", null, null, null);
assertEquals(HttpStatusCode.NOT_ACCEPTABLE.getStatusCode(), response.getStatusCode());
}
@Test
public void testContentNegotiationNotSupported2() {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("$metadata");
request.setRawQueryPath("$format=notSupported");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void contentNegotiationNotSupported2() {
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", "$format=notSupported", null, null, null);
assertEquals(HttpStatusCode.NOT_ACCEPTABLE.getStatusCode(), response.getStatusCode());
}
@Test
public void testUnregisteredProcessor() {
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("ESAllPrim");
ODataResponse response = handler.process(request);
assertNotNull(response);
public void unregisteredProcessor() {
final ODataResponse response = dispatch(HttpMethod.GET, "ESAllPrim", null);
assertEquals(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), response.getStatusCode());
}
@Test
public void testCount() throws Exception {
public void uriParserExceptionResultsInRightResponseNotFound() throws Exception {
final ODataResponse response = dispatch(HttpMethod.GET, "NotFound", null);
assertEquals(HttpStatusCode.NOT_FOUND.getStatusCode(), response.getStatusCode());
}
@Test
public void uriParserExceptionResultsInRightResponseBadRequest() throws Exception {
final ODataResponse response = dispatch(HttpMethod.GET, "ESAllPrim('122')", null);
assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), response.getStatusCode());
}
@Test
public void applicationExceptionInProcessor() throws Exception {
MetadataProcessor processor = mock(MetadataProcessor.class);
doThrow(new ODataApplicationException("msg", 425, Locale.ENGLISH)).when(processor).readMetadata(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
final ODataResponse response = dispatch(HttpMethod.GET, "$metadata", processor);
assertEquals(425, response.getStatusCode());
}
@Test
public void uriParserExceptionResultsInRightResponseEdmCause() throws Exception {
final OData odata = OData.newInstance();
final ServiceMetadata serviceMetadata = odata.createServiceMetadata(
new EdmProvider() {
public EntitySet getEntitySet(final FullQualifiedName entityContainer, final String entitySetName)
throws ODataException {
throw new ODataException("msg");
}
},
Collections.<EdmxReference> emptyList());
ODataRequest request = new ODataRequest();
request.setMethod(HttpMethod.GET);
request.setRawODataPath("ESAllPrim/$count");
request.setRawODataPath("EdmException");
EntitySetProcessor processor = mock(EntitySetProcessor.class);
handler.register(processor);
ODataResponse response = handler.process(request);
final ODataResponse response = new ODataHandler(odata, serviceMetadata).process(request);
assertNotNull(response);
Mockito.verify(processor).countEntitySet(
Mockito.eq(request),
Mockito.any(ODataResponse.class),
Mockito.any(UriInfo.class));
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
}
@Test
public void dispatchEntitySet() throws Exception {
final EntityCollectionProcessor processor = mock(EntityCollectionProcessor.class);
dispatch(HttpMethod.GET, "ESAllPrim", processor);
verify(processor).readEntityCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
}
@Test
public void dispatchEntitySetCount() throws Exception {
final CountEntityCollectionProcessor processor = mock(CountEntityCollectionProcessor.class);
dispatch(HttpMethod.GET, "ESAllPrim/$count", processor);
verify(processor).countEntityCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), eq(ContentType.TEXT_PLAIN));
dispatchMethodNotAllowed(HttpMethod.POST, "ESAllPrim/$count", processor);
}
@Test
public void dispatchCountWithNavigation() throws Exception {
ODataRequest request = new ODataRequest();
final CountEntityCollectionProcessor processor = mock(CountEntityCollectionProcessor.class);
dispatch(HttpMethod.GET, "ESAllPrim(0)/NavPropertyETTwoPrimMany/$count", processor);
request.setMethod(HttpMethod.GET);
request.setRawODataPath("ESAllPrim(0)/NavPropertyETTwoPrimMany/$count");
EntitySetProcessor processor = mock(EntitySetProcessor.class);
handler.register(processor);
ODataResponse response = handler.process(request);
assertNotNull(response);
Mockito.verify(processor).countEntitySet(
Mockito.eq(request),
Mockito.any(ODataResponse.class),
Mockito.any(UriInfo.class));
verify(processor).countEntityCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), eq(ContentType.TEXT_PLAIN));
}
@Test
public void dispatchAddressPrimitiveProperty() throws Exception {
ODataRequest request = new ODataRequest();
public void dispatchEntity() throws Exception {
final EntityProcessor processor = mock(EntityProcessor.class);
dispatch(HttpMethod.GET, "ESAllPrim(0)", processor);
request.setMethod(HttpMethod.GET);
request.setRawODataPath("ESAllPrim(0)/PropertyInt16");
PropertyProcessor processor = mock(PropertyProcessor.class);
handler.register(processor);
ODataResponse response = handler.process(request);
assertNotNull(response);
Mockito.verify(processor).readProperty(
Mockito.any(ODataRequest.class),
Mockito.any(ODataResponse.class),
Mockito.any(UriInfo.class),
Mockito.any(ContentType.class));
verify(processor).readEntity(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
}
@Test
public void dispatchAddressPrimitivePropertyValue() throws Exception {
ODataRequest request = new ODataRequest();
public void dispatchPrimitiveProperty() throws Exception {
final PrimitiveProcessor processor = mock(PrimitiveProcessor.class);
dispatch(HttpMethod.GET, "ESAllPrim(0)/PropertyInt16", processor);
request.setMethod(HttpMethod.GET);
request.setRawODataPath("ESAllPrim(0)/PropertyInt16/$value");
PropertyProcessor processor = mock(PropertyProcessor.class);
handler.register(processor);
ODataResponse response = handler.process(request);
assertNotNull(response);
Mockito.verify(processor).readPropertyValue(
Mockito.any(ODataRequest.class),
Mockito.any(ODataResponse.class),
Mockito.any(UriInfo.class),
Mockito.any(ContentType.class));
verify(processor).readPrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
}
@Test
public void dispatchAddressComplexProperty() throws Exception {
ODataRequest request = new ODataRequest();
public void dispatchPrimitivePropertyValue() throws Exception {
final PrimitiveProcessor processor = mock(PrimitiveProcessor.class);
dispatch(HttpMethod.GET, "ESAllPrim(0)/PropertyInt16/$value", processor);
request.setMethod(HttpMethod.GET);
request.setRawODataPath("ESMixPrimCollComp(7)/PropertyComp");
PropertyProcessor processor = mock(PropertyProcessor.class);
handler.register(processor);
ODataResponse response = handler.process(request);
assertNotNull(response);
Mockito.verify(processor).readProperty(
Mockito.any(ODataRequest.class),
Mockito.any(ODataResponse.class),
Mockito.any(UriInfo.class),
Mockito.any(ContentType.class));
verify(processor).readPrimitiveAsValue(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
}
}
@Test
public void dispatchPrimitiveCollectionProperty() throws Exception {
final PrimitiveCollectionProcessor processor = mock(PrimitiveCollectionProcessor.class);
dispatch(HttpMethod.GET, "ESMixPrimCollComp(7)/CollPropertyString", processor);
verify(processor).readPrimitiveCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
}
@Test
public void dispatchComplexProperty() throws Exception {
final ComplexProcessor processor = mock(ComplexProcessor.class);
dispatch(HttpMethod.GET, "ESMixPrimCollComp(7)/PropertyComp", processor);
verify(processor).readComplex(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
}
@Test
public void dispatchComplexCollectionProperty() throws Exception {
final ComplexCollectionProcessor processor = mock(ComplexCollectionProcessor.class);
dispatch(HttpMethod.GET, "ESMixPrimCollComp(7)/CollPropertyComp", processor);
verify(processor).readComplexCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
}
private ODataResponse dispatch(final HttpMethod method, final String path, final String query,
final String headerName, final String headerValue, final Processor processor) {
ODataRequest request = new ODataRequest();
request.setMethod(method);
request.setRawBaseUri(BASE_URI);
if (path.isEmpty()) {
request.setRawRequestUri(BASE_URI);
}
request.setRawODataPath(path);
request.setRawQueryPath(query);
if (headerName != null) {
request.addHeader(headerName, Collections.singletonList(headerValue));
}
final OData odata = OData.newInstance();
final ServiceMetadata metadata = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList());
ODataHandler handler = new ODataHandler(odata, metadata);
if (processor != null) {
handler.register(processor);
}
final ODataResponse response = handler.process(request);
assertNotNull(response);
return response;
}
private ODataResponse dispatch(final HttpMethod method, final String path, final Processor processor) {
return dispatch(method, path, null, null, null, processor);
}
private void dispatchMethodNotAllowed(final HttpMethod method, final String path, final Processor processor) {
final ODataResponse response = dispatch(method, path, processor);
assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
assertNotNull(response.getContent());
}
}

View File

@ -31,16 +31,22 @@ import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.edm.Edm;
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.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.core.data.PropertyImpl;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
@ -58,7 +64,7 @@ import org.mockito.Mockito;
public class ODataJsonSerializerTest {
private static final Edm edm = OData.newInstance().createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference>emptyList()).getEdm();
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
private static final EdmEntityContainer entityContainer = edm.getEntityContainer(
new FullQualifiedName("olingo.odata.test1", "Container"));
private final DataProvider data = new DataProvider();
@ -68,8 +74,8 @@ public class ODataJsonSerializerTest {
public void entitySimple() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build());
final String resultString = IOUtils.toString(result);
@ -100,8 +106,8 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
entity.getProperties().retainAll(Arrays.asList(entity.getProperties().get(0)));
final String resultString = IOUtils.toString(serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
final String resultString = IOUtils.toString(serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build()));
final String expectedResult = "{\"@odata.context\":\"$metadata#ESAllPrim/$entity\","
@ -121,8 +127,8 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
entity.getProperties().clear();
serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build());
}
@ -133,8 +139,8 @@ public class ODataJsonSerializerTest {
Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
entity.getProperties().get(0).setValue(ValueType.PRIMITIVE, false);
try {
serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build());
Assert.fail("Expected exception not thrown!");
@ -154,8 +160,8 @@ public class ODataJsonSerializerTest {
entitySet.setNext(URI.create("/next"));
CountOption countOption = Mockito.mock(CountOption.class);
Mockito.when(countOption.getValue()).thenReturn(true);
InputStream result = serializer.entitySet(edmEntitySet, entitySet,
ODataSerializerOptions.with()
InputStream result = serializer.entityCollection(edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
.count(countOption)
.build());
@ -179,8 +185,8 @@ public class ODataJsonSerializerTest {
public void entityCollAllPrim() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().serviceRoot(URI.create("http://host/service/"))
.entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build());
@ -215,8 +221,8 @@ public class ODataJsonSerializerTest {
public void entityCompAllPrim() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompAllPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build());
final String resultString = IOUtils.toString(result);
@ -248,8 +254,8 @@ public class ODataJsonSerializerTest {
public void entityMixPrimCollComp() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build());
final String resultString = IOUtils.toString(result);
@ -271,8 +277,8 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
entity.getProperties().retainAll(Arrays.asList(entity.getProperties().get(0)));
final String resultString = IOUtils.toString(serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
final String resultString = IOUtils.toString(serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build()));
final String expectedResult = "{\"@odata.context\":\"$metadata#ESMixPrimCollComp/$entity\","
@ -286,7 +292,7 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA)
.entity(edmEntitySet, entity, null);
.entity(edmEntitySet.getEntityType(), entity, null);
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}";
Assert.assertEquals(expectedResult, resultString);
@ -297,8 +303,8 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final EntitySet entitySet = data.readAll(edmEntitySet);
InputStream result = new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA)
.entitySet(edmEntitySet, entitySet,
ODataSerializerOptions.with()
.entityCollection(edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build()).build());
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"value\":["
@ -314,8 +320,8 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia");
Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
entity.setMediaETag("theMediaETag");
final String resultString = IOUtils.toString(serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
final String resultString = IOUtils.toString(serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build()));
final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia/$entity\","
@ -328,8 +334,8 @@ public class ODataJsonSerializerTest {
public void entitySetMedia() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia");
final EntitySet entitySet = data.readAll(edmEntitySet);
final String resultString = IOUtils.toString(serializer.entitySet(edmEntitySet, entitySet,
ODataSerializerOptions.with()
final String resultString = IOUtils.toString(serializer.entityCollection(edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build()).build()));
final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia\",\"value\":["
+ "{\"@odata.mediaContentType\":\"image/png\",\"PropertyInt16\":1},"
@ -342,16 +348,17 @@ public class ODataJsonSerializerTest {
@Test
public void select() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
final SelectItem selectItem1 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyDate");
final SelectItem selectItem2 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyBoolean");
final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(
selectItem1, selectItem2, selectItem2));
InputStream result = serializer
.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
.entity(entityType, entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(serializer.buildContextURLSelectList(edmEntitySet, null, select))
.selectList(serializer.buildContextURLSelectList(entityType, null, select))
.suffix(Suffix.ENTITY).build())
.select(select)
.build());
@ -370,8 +377,8 @@ public class ODataJsonSerializerTest {
SelectItem selectItem2 = Mockito.mock(SelectItem.class);
Mockito.when(selectItem2.isStar()).thenReturn(true);
final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem1, selectItem2));
InputStream result = serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.select(select)
.build());
@ -384,14 +391,15 @@ public class ODataJsonSerializerTest {
@Test
public void selectComplex() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompComp");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final EntitySet entitySet = data.readAll(edmEntitySet);
final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(
ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyComp", "PropertyComp", "PropertyString")));
InputStream result = serializer
.entitySet(edmEntitySet, entitySet,
ODataSerializerOptions.with()
.entityCollection(entityType, entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(serializer.buildContextURLSelectList(edmEntitySet, null, select))
.selectList(serializer.buildContextURLSelectList(entityType, null, select))
.build())
.select(select)
.build());
@ -407,15 +415,16 @@ public class ODataJsonSerializerTest {
@Test
public void selectComplexTwice() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompComp");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final EntitySet entitySet = data.readAll(edmEntitySet);
final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(
ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyComp", "PropertyComp", "PropertyString"),
ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyComp", "PropertyComp")));
final String resultString = IOUtils.toString(serializer
.entitySet(edmEntitySet, entitySet,
ODataSerializerOptions.with()
.entityCollection(entityType, entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(serializer.buildContextURLSelectList(edmEntitySet, null, select))
.selectList(serializer.buildContextURLSelectList(entityType, null, select))
.build())
.select(select)
.build()));
@ -433,8 +442,8 @@ public class ODataJsonSerializerTest {
final Entity entity = data.readAll(edmEntitySet).getEntities().get(3);
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList(
ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETAllPrimOne")));
InputStream result = serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.expand(expand)
.build());
@ -464,6 +473,7 @@ public class ODataJsonSerializerTest {
@Test
public void expandSelect() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final Entity entity = data.readAll(edmEntitySet).getEntities().get(3);
final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(
ExpandSelectMock.mockSelectItem(entityContainer.getEntitySet("ESAllPrim"), "PropertyDate")));
@ -471,10 +481,10 @@ public class ODataJsonSerializerTest {
Mockito.when(expandItem.getSelectOption()).thenReturn(select);
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList(expandItem));
final String resultString = IOUtils.toString(serializer
.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
.entity(entityType, entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select))
.selectList(serializer.buildContextURLSelectList(entityType, expand, select))
.suffix(Suffix.ENTITY).build())
.expand(expand)
.build()));
@ -488,6 +498,7 @@ public class ODataJsonSerializerTest {
@Test
public void expandAll() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
final ExpandItem expandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETTwoPrimOne");
ExpandItem expandItemAll = Mockito.mock(ExpandItem.class);
@ -497,10 +508,10 @@ public class ODataJsonSerializerTest {
final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(
ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertySByte")));
final String resultString = IOUtils.toString(serializer
.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
.entity(entityType, entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select))
.selectList(serializer.buildContextURLSelectList(entityType, expand, select))
.suffix(Suffix.ENTITY).build())
.expand(expand)
.select(select)
@ -516,6 +527,7 @@ public class ODataJsonSerializerTest {
@Test
public void expandNoData() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final Entity entity = data.readAll(edmEntitySet).getEntities().get(1);
ExpandItem expandItemAll = Mockito.mock(ExpandItem.class);
Mockito.when(expandItemAll.isStar()).thenReturn(true);
@ -523,10 +535,10 @@ public class ODataJsonSerializerTest {
final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(
ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyTimeOfDay")));
final String resultString = IOUtils.toString(serializer
.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
.entity(entityType, entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select))
.selectList(serializer.buildContextURLSelectList(entityType, expand, select))
.suffix(Suffix.ENTITY).build())
.expand(expand)
.select(select)
@ -541,6 +553,7 @@ public class ODataJsonSerializerTest {
@Test
public void expandTwoLevels() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final EdmEntitySet innerEntitySet = entityContainer.getEntitySet("ESAllPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(1);
ExpandItem expandItemSecond = Mockito.mock(ExpandItem.class);
@ -553,10 +566,10 @@ public class ODataJsonSerializerTest {
Mockito.when(expandItemFirst.getSelectOption()).thenReturn(select);
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList(expandItemFirst));
final String resultString = IOUtils.toString(serializer
.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
.entity(entityType, entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select))
.selectList(serializer.buildContextURLSelectList(entityType, expand, select))
.suffix(Suffix.ENTITY).build())
.expand(expand)
.build()));
@ -579,8 +592,8 @@ public class ODataJsonSerializerTest {
final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyString");
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
final String resultString = IOUtils.toString(serializer
.entityProperty(edmProperty, property,
ODataSerializerOptions.with()
.primitive((EdmPrimitiveType) edmProperty.getType(), property,
PrimitiveSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName())
.build())
@ -596,8 +609,8 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyString");
final Property property = new PropertyImpl("Edm.String", edmProperty.getName(), ValueType.PRIMITIVE, null);
serializer.entityProperty(edmProperty, property,
ODataSerializerOptions.with()
serializer.primitive((EdmPrimitiveType) edmProperty.getType(), property,
PrimitiveSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("4242").navOrPropertyPath(edmProperty.getName())
.build())
@ -611,8 +624,8 @@ public class ODataJsonSerializerTest {
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
final String resultString = IOUtils.toString(serializer
.entityProperty(edmProperty, property,
ODataSerializerOptions.with()
.primitiveCollection((EdmPrimitiveType) edmProperty.getType(), property,
PrimitiveSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName())
.build())
@ -630,8 +643,8 @@ public class ODataJsonSerializerTest {
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty("PropertyComp");
final String resultString = IOUtils.toString(serializer
.entityProperty(edmProperty, property,
ODataSerializerOptions.with()
.complex((EdmComplexType) edmProperty.getType(), property,
ComplexSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName())
.build())
@ -641,4 +654,25 @@ public class ODataJsonSerializerTest {
+ "\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"}",
resultString);
}
@Test
public void complexCollectionProperty() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
final String resultString = IOUtils.toString(serializer
.complexCollection((EdmComplexType) edmProperty.getType(), property,
ComplexSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName())
.build())
.build()));
Assert.assertEquals("{"
+ "\"@odata.context\":\"$metadata#ESMixPrimCollComp(32767)/CollPropertyComp\","
+ "\"value\":[{\"PropertyInt16\":123,\"PropertyString\":\"TEST 1\"},"
+ "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"},"
+ "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}]}",
resultString);
}
}

View File

@ -266,7 +266,6 @@ public class UriValidatorTest {
validator.validate(uri, HttpMethod.PUT);
validator.validate(uri, HttpMethod.DELETE);
validator.validate(uri, HttpMethod.PATCH);
validator.validate(uri, HttpMethod.MERGE);
}
@Test

View File

@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.olingo.commons.api.ODataException;
import org.apache.olingo.commons.api.data.Entity;
@ -41,8 +40,6 @@ import org.apache.olingo.server.api.uri.UriParameter;
public class DataProvider {
private static final UUID GUID = UUID.fromString("01234567-89ab-cdef-0123-456789abcdef");
private Map<String, EntitySet> data;
public DataProvider() {

View File

@ -27,7 +27,9 @@ import org.apache.olingo.commons.api.data.ContextURL.Suffix;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
@ -38,11 +40,15 @@ import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.EntitySetProcessor;
import org.apache.olingo.server.api.processor.PropertyProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoResource;
@ -59,7 +65,8 @@ import org.apache.olingo.server.sample.data.DataProvider.DataProviderException;
* This is a very simple example which should give you a rough guideline on how to implement such an processor.
* See the JavaDoc of the server.api interfaces for more information.
*/
public class CarsProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor {
public class CarsProcessor implements EntityCollectionProcessor, EntityProcessor,
PrimitiveProcessor, ComplexProcessor {
private OData odata;
private DataProvider dataProvider;
@ -76,7 +83,7 @@ public class CarsProcessor implements EntitySetProcessor, EntityProcessor, Prope
}
@Override
public void readEntitySet(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
public void readEntityCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
// First we have to figure out which entity set to use
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
@ -93,8 +100,8 @@ public class CarsProcessor implements EntitySetProcessor, EntityProcessor, Prope
// Now the content is serialized using the serializer.
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
InputStream serializedContent = serializer.entitySet(edmEntitySet, entitySet,
ODataSerializerOptions.with()
InputStream serializedContent = serializer.entityCollection(edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, false, expand, select, null))
.count(uriInfo.getCountOption())
@ -131,11 +138,10 @@ public class CarsProcessor implements EntitySetProcessor, EntityProcessor, Prope
ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
InputStream serializedContent = serializer.entity(edmEntitySet, entity,
ODataSerializerOptions.with()
InputStream serializedContent = serializer.entity(edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, true, expand, select, null))
.count(uriInfo.getCountOption())
.expand(expand).select(select)
.build());
response.setContent(serializedContent);
@ -144,9 +150,8 @@ public class CarsProcessor implements EntitySetProcessor, EntityProcessor, Prope
}
}
@Override
public void readProperty(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType contentType)
throws ODataApplicationException, SerializerException {
private void readProperty(ODataResponse response, UriInfo uriInfo, ContentType contentType,
boolean complex) throws ODataApplicationException, SerializerException {
// To read a property we have to first get the entity out of the entity set
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
Entity entity;
@ -175,11 +180,13 @@ public class CarsProcessor implements EntitySetProcessor, EntityProcessor, Prope
} else {
final ODataFormat format = ODataFormat.fromContentType(contentType);
ODataSerializer serializer = odata.createSerializer(format);
InputStream serializerContent = serializer.entityProperty(edmProperty, property,
ODataSerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, true, null, null, edmProperty.getName()))
.build());
final ContextURL contextURL = format == ODataFormat.JSON_NO_METADATA ? null :
getContextUrl(serializer, edmEntitySet, true, null, null, edmProperty.getName());
InputStream serializerContent = complex ?
serializer.complex((EdmComplexType) edmProperty.getType(), property,
ComplexSerializerOptions.with().contextURL(contextURL).build()) :
serializer.primitive((EdmPrimitiveType) edmProperty.getType(), property,
PrimitiveSerializerOptions.with().contextURL(contextURL).build());
response.setContent(serializerContent);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
@ -187,22 +194,7 @@ public class CarsProcessor implements EntitySetProcessor, EntityProcessor, Prope
}
}
}
@Override
public void readPropertyValue(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType contentType)
throws ODataApplicationException, SerializerException {
throw new ODataApplicationException("Not implemented for this sample", HttpStatusCode.NOT_IMPLEMENTED
.getStatusCode(), Locale.ENGLISH);
}
@Override
public void countEntitySet(ODataRequest request, ODataResponse response, UriInfo uriInfo)
throws ODataApplicationException, SerializerException {
// In this example we do not support the count system query option so we throw an exception
throw new ODataApplicationException("Not implemented for this sample", HttpStatusCode.NOT_IMPLEMENTED
.getStatusCode(), Locale.ENGLISH);
}
private Entity readEntityInternal(final UriInfoResource uriInfo, final EdmEntitySet entitySet)
throws DataProvider.DataProviderException {
// This method will extract the key values and pass them to the data provider
@ -234,9 +226,28 @@ public class CarsProcessor implements EntitySetProcessor, EntityProcessor, Prope
throws SerializerException {
return ContextURL.with().entitySet(entitySet)
.selectList(serializer.buildContextURLSelectList(entitySet, expand, select))
.selectList(serializer.buildContextURLSelectList(entitySet.getEntityType(), expand, select))
.suffix(isSingleEntity ? Suffix.ENTITY : null)
.navOrPropertyPath(navOrPropertyPath)
.build();
}
@Override
public void readPrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException {
readProperty(response, uriInfo, format, false);
}
@Override
public void readComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException {
readProperty(response, uriInfo, format, true);
}
@Override
public void readPrimitiveAsValue(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
throws ODataApplicationException, SerializerException {
throw new ODataApplicationException("Not implemented for this sample",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH);
}
}