/*******************************************************************************
* Copyright 2013 SAP AG
*
* Licensed 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 com.sap.core.odata.core;
import java.io.InputStream;
import com.sap.core.odata.api.ODataService;
import com.sap.core.odata.api.ODataServiceFactory;
import com.sap.core.odata.api.batch.BatchHandler;
import com.sap.core.odata.api.commons.ODataHttpMethod;
import com.sap.core.odata.api.exception.ODataBadRequestException;
import com.sap.core.odata.api.exception.ODataException;
import com.sap.core.odata.api.exception.ODataMethodNotAllowedException;
import com.sap.core.odata.api.processor.ODataProcessor;
import com.sap.core.odata.api.processor.ODataResponse;
import com.sap.core.odata.api.processor.part.BatchProcessor;
import com.sap.core.odata.api.processor.part.EntityComplexPropertyProcessor;
import com.sap.core.odata.api.processor.part.EntityLinkProcessor;
import com.sap.core.odata.api.processor.part.EntityLinksProcessor;
import com.sap.core.odata.api.processor.part.EntityMediaProcessor;
import com.sap.core.odata.api.processor.part.EntityProcessor;
import com.sap.core.odata.api.processor.part.EntitySetProcessor;
import com.sap.core.odata.api.processor.part.EntitySimplePropertyProcessor;
import com.sap.core.odata.api.processor.part.EntitySimplePropertyValueProcessor;
import com.sap.core.odata.api.processor.part.FunctionImportProcessor;
import com.sap.core.odata.api.processor.part.FunctionImportValueProcessor;
import com.sap.core.odata.api.processor.part.MetadataProcessor;
import com.sap.core.odata.api.processor.part.ServiceDocumentProcessor;
import com.sap.core.odata.core.batch.BatchHandlerImpl;
import com.sap.core.odata.core.exception.ODataRuntimeException;
import com.sap.core.odata.core.uri.UriInfoImpl;
/**
* Request dispatching according to URI type and HTTP method.
* @author SAP AG
*/
public class Dispatcher {
private final ODataService service;
private final ODataServiceFactory serviceFactory;
public Dispatcher(final ODataServiceFactory serviceFactory, final ODataService service) {
this.service = service;
this.serviceFactory = serviceFactory;
}
public ODataResponse dispatch(final ODataHttpMethod method, final UriInfoImpl uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
switch (uriInfo.getUriType()) {
case URI0:
if (method == ODataHttpMethod.GET) {
return service.getServiceDocumentProcessor().readServiceDocument(uriInfo, contentType);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI1:
case URI6B:
switch (method) {
case GET:
return service.getEntitySetProcessor().readEntitySet(uriInfo, contentType);
case POST:
return service.getEntitySetProcessor().createEntity(uriInfo, content, requestContentType, contentType);
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI2:
switch (method) {
case GET:
return service.getEntityProcessor().readEntity(uriInfo, contentType);
case PUT:
return service.getEntityProcessor().updateEntity(uriInfo, content, requestContentType, false, contentType);
case PATCH:
case MERGE:
return service.getEntityProcessor().updateEntity(uriInfo, content, requestContentType, true, contentType);
case DELETE:
return service.getEntityProcessor().deleteEntity(uriInfo, contentType);
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI3:
switch (method) {
case GET:
return service.getEntityComplexPropertyProcessor().readEntityComplexProperty(uriInfo, contentType);
case PUT:
return service.getEntityComplexPropertyProcessor().updateEntityComplexProperty(uriInfo, content, requestContentType, false, contentType);
case PATCH:
case MERGE:
return service.getEntityComplexPropertyProcessor().updateEntityComplexProperty(uriInfo, content, requestContentType, true, contentType);
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI4:
case URI5:
switch (method) {
case GET:
if (uriInfo.isValue()) {
return service.getEntitySimplePropertyValueProcessor().readEntitySimplePropertyValue(uriInfo, contentType);
} else {
return service.getEntitySimplePropertyProcessor().readEntitySimpleProperty(uriInfo, contentType);
}
case PUT:
case PATCH:
case MERGE:
if (uriInfo.isValue()) {
return service.getEntitySimplePropertyValueProcessor().updateEntitySimplePropertyValue(uriInfo, content, requestContentType, contentType);
} else {
return service.getEntitySimplePropertyProcessor().updateEntitySimpleProperty(uriInfo, content, requestContentType, contentType);
}
case DELETE:
if (uriInfo.isValue()) {
return service.getEntitySimplePropertyValueProcessor().deleteEntitySimplePropertyValue(uriInfo, contentType);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI6A:
switch (method) {
case GET:
return service.getEntityProcessor().readEntity(uriInfo, contentType);
case PUT:
case PATCH:
case MERGE:
case DELETE:
throw new ODataBadRequestException(ODataBadRequestException.NOTSUPPORTED);
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI7A:
switch (method) {
case GET:
return service.getEntityLinkProcessor().readEntityLink(uriInfo, contentType);
case PUT:
case PATCH:
case MERGE:
return service.getEntityLinkProcessor().updateEntityLink(uriInfo, content, requestContentType, contentType);
case DELETE:
return service.getEntityLinkProcessor().deleteEntityLink(uriInfo, contentType);
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI7B:
switch (method) {
case GET:
return service.getEntityLinksProcessor().readEntityLinks(uriInfo, contentType);
case POST:
return service.getEntityLinksProcessor().createEntityLink(uriInfo, content, requestContentType, contentType);
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI8:
if (method == ODataHttpMethod.GET) {
return service.getMetadataProcessor().readMetadata(uriInfo, contentType);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI9:
if (method == ODataHttpMethod.POST) {
BatchHandler handler = new BatchHandlerImpl(serviceFactory, service);
return service.getBatchProcessor().executeBatch(handler, requestContentType, content);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI10:
case URI11:
case URI12:
case URI13:
return service.getFunctionImportProcessor().executeFunctionImport(uriInfo, contentType);
case URI14:
if (uriInfo.isValue()) {
return service.getFunctionImportValueProcessor().executeFunctionImportValue(uriInfo, contentType);
} else {
return service.getFunctionImportProcessor().executeFunctionImport(uriInfo, contentType);
}
case URI15:
if (method == ODataHttpMethod.GET) {
return service.getEntitySetProcessor().countEntitySet(uriInfo, contentType);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI16:
if (method == ODataHttpMethod.GET) {
return service.getEntityProcessor().existsEntity(uriInfo, contentType);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI17:
switch (method) {
case GET:
return service.getEntityMediaProcessor().readEntityMedia(uriInfo, contentType);
case PUT:
return service.getEntityMediaProcessor().updateEntityMedia(uriInfo, content, requestContentType, contentType);
case DELETE:
return service.getEntityMediaProcessor().deleteEntityMedia(uriInfo, contentType);
default:
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI50A:
if (method == ODataHttpMethod.GET) {
return service.getEntityLinkProcessor().existsEntityLink(uriInfo, contentType);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
case URI50B:
if (method == ODataHttpMethod.GET) {
return service.getEntityLinksProcessor().countEntityLinks(uriInfo, contentType);
} else {
throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
}
default:
throw new ODataRuntimeException("Unknown or not implemented URI type: " + uriInfo.getUriType());
}
}
protected static Class<? extends ODataProcessor> mapUriTypeToProcessorFeature(final UriInfoImpl uriInfo) {
Class<? extends ODataProcessor> feature;
switch (uriInfo.getUriType()) {
case URI0:
feature = ServiceDocumentProcessor.class;
break;
case URI1:
case URI6B:
case URI15:
feature = EntitySetProcessor.class;
break;
case URI2:
case URI6A:
case URI16:
feature = EntityProcessor.class;
break;
case URI3:
feature = EntityComplexPropertyProcessor.class;
break;
case URI4:
case URI5:
feature = uriInfo.isValue() ? EntitySimplePropertyValueProcessor.class : EntitySimplePropertyProcessor.class;
break;
case URI7A:
case URI50A:
feature = EntityLinkProcessor.class;
break;
case URI7B:
case URI50B:
feature = EntityLinksProcessor.class;
break;
case URI8:
feature = MetadataProcessor.class;
break;
case URI9:
feature = BatchProcessor.class;
break;
case URI10:
case URI11:
case URI12:
case URI13:
feature = FunctionImportProcessor.class;
break;
case URI14:
feature = uriInfo.isValue() ? FunctionImportValueProcessor.class : FunctionImportProcessor.class;
break;
case URI17:
feature = EntityMediaProcessor.class;
break;
default:
throw new ODataRuntimeException("Unknown or not implemented URI type: " + uriInfo.getUriType());
}
return feature;
}
}