org.apache.olingo.ext.proxy.commons.InvokerInvocationHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of odata-client-proxy Show documentation
Show all versions of odata-client-proxy Show documentation
Java client API for OData services: Proxy.
/*
* 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.ext.proxy.commons;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.olingo.client.api.communication.request.invoke.ClientNoContent;
import org.apache.olingo.client.api.uri.URIBuilder;
import org.apache.olingo.client.api.uri.URIFilter;
import org.apache.olingo.client.core.uri.URIUtils;
import org.apache.olingo.client.api.domain.ClientEntity;
import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.domain.ClientInvokeResult;
import org.apache.olingo.client.api.domain.ClientProperty;
import org.apache.olingo.client.api.domain.ClientValue;
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmOperation;
import org.apache.olingo.commons.api.edm.EdmReturnType;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.commons.core.edm.EdmTypeInfo;
import org.apache.olingo.ext.proxy.AbstractService;
import org.apache.olingo.ext.proxy.api.ComplexCollection;
import org.apache.olingo.ext.proxy.api.EntityCollection;
import org.apache.olingo.ext.proxy.api.OperationType;
import org.apache.olingo.ext.proxy.api.Operations;
import org.apache.olingo.ext.proxy.api.PrimitiveCollection;
import org.apache.olingo.ext.proxy.api.Sort;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.utils.ClassUtils;
import org.apache.olingo.ext.proxy.utils.CoreUtils;
import org.apache.olingo.ext.proxy.utils.ProxyUtils;
public class InvokerInvocationHandler extends AbstractInvocationHandler {
private final URI baseURI;
private URIBuilder uri;
private final Map parameters;
private final Operation operation;
private final EdmOperation edmOperation;
protected final Class targetRef;
private final Class> operationRef;
public InvokerInvocationHandler(
final URI uri,
final Map parameters,
final Operation operation,
final EdmOperation edmOperation,
final Type[] references,
final AbstractService> service) {
super(service);
this.baseURI = uri;
this.uri = this.baseURI == null ? null : service.getClient().newURIBuilder(this.baseURI.toASCIIString());
this.parameters = parameters;
this.operation = operation;
this.edmOperation = edmOperation;
if (references.length > 0) {
this.targetRef = ClassUtils.getTypeClass(references[0]);
this.operationRef = references.length > 1 ? ClassUtils.getTypeClass(references[1]) : null;
} else {
this.targetRef = null;
this.operationRef = null;
}
}
public Future executeAsync() {
return service.getClient().getConfiguration().getExecutor().submit(new Callable() {
@Override
public T call() throws Exception {
return execute();
}
});
}
@SuppressWarnings({"unchecked", "rawtypes"})
public T execute() {
if (operation == null || uri == null) {
throw new IllegalStateException("Invalid operation");
}
try {
// 1. IMPORTANT: flush any pending change *before* invoke if this operation is side effecting
if (operation.type() == OperationType.ACTION) {
service.getPersistenceManager().flush();
}
// 2. invoke
final ClientInvokeResult result = service.getClient().getInvokeRequestFactory().getInvokeRequest(
edmOperation instanceof EdmFunction ? HttpMethod.GET : HttpMethod.POST,
uri.build(),
getResultReference(edmOperation.getReturnType()),
parameters).
execute().getBody();
// 3. process invoke result
if (StringUtils.isBlank(operation.returnType())) {
return (T) ClassUtils.returnVoid();
}
final EdmTypeInfo returnType = new EdmTypeInfo.Builder().
setEdm(service.getClient().getCachedEdm()).setTypeExpression(operation.returnType()).build();
if (returnType.isEntityType()) {
if (returnType.isCollection()) {
final Class> collItemType = ClassUtils.extractTypeArg(targetRef, EntityCollection.class);
return (T) ProxyUtils.getEntityCollectionProxy(
service,
collItemType,
targetRef,
null,
(ClientEntitySet) result,
this.baseURI,
false);
} else {
return (T) ProxyUtils.getEntityProxy(
service,
(ClientEntity) result,
null,
targetRef,
null,
false);
}
} else {
Object res;
final Class> ref = ClassUtils.getTypeClass(targetRef);
final ClientProperty property = (ClientProperty) result;
if (property == null || property.hasNullValue()) {
res = null;
} else if (returnType.isCollection()) {
if (returnType.isComplexType()) {
final Class> itemRef = ClassUtils.extractTypeArg(ref, ComplexCollection.class);
final List items = new ArrayList();
for (ClientValue item : property.getValue().asCollection()) {
items.add(ProxyUtils.getComplexProxy(
service,
property.getName(),
item,
itemRef,
null,
null,
true));
}
res = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class>[] {ref}, new ComplexCollectionInvocationHandler(
service,
items,
itemRef,
null));
} else {
final List items = new ArrayList();
for (ClientValue item : property.getValue().asCollection()) {
items.add(item.asPrimitive().toValue());
}
res = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class>[] {PrimitiveCollection.class}, new PrimitiveCollectionInvocationHandler(
service,
items,
null,
null));
}
} else {
if (returnType.isComplexType()) {
res = ProxyUtils.getComplexProxy(
service, property.getName(), property.getValue().asComplex(), ref, null, null, false);
} else {
res = CoreUtils.getObjectFromODataValue(property.getValue(), targetRef, service);
}
}
return (T) res;
}
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
@SuppressWarnings("unchecked")
private Class getResultReference(final EdmReturnType returnType) {
Class result;
if (returnType == null) {
result = (Class) ClientNoContent.class;
} else {
if (returnType.isCollection() && returnType.getType().getKind() == EdmTypeKind.ENTITY) {
result = (Class) ClientEntitySet.class;
} else if (!returnType.isCollection() && returnType.getType().getKind() == EdmTypeKind.ENTITY) {
result = (Class) ClientEntity.class;
} else {
result = (Class) ClientProperty.class;
}
}
return result;
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("filter".equals(method.getName())
|| "orderBy".equals(method.getName())
|| "top".equals(method.getName())
|| "skip".equals(method.getName())
|| "expand".equals(method.getName())
|| "select".equals(method.getName())) {
invokeSelfMethod(method, args);
return proxy;
} else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
final EdmTypeInfo returnType = new EdmTypeInfo.Builder().
setEdm(service.getClient().getCachedEdm()).setTypeExpression(operation.returnType()).build();
final URI prefixURI = URIUtils.buildFunctionInvokeURI(this.baseURI, parameters);
OperationInvocationHandler handler;
if (returnType.isComplexType()) {
if (returnType.isCollection()) {
handler = OperationInvocationHandler.getInstance(new ComplexCollectionInvocationHandler(
targetRef, service, getClient().newURIBuilder(prefixURI.toASCIIString())));
} else {
handler = OperationInvocationHandler.getInstance(ComplexInvocationHandler.getInstance(
targetRef, service, getClient().newURIBuilder(prefixURI.toASCIIString())));
}
} else {
if (returnType.isCollection()) {
handler = OperationInvocationHandler.getInstance(new EntityCollectionInvocationHandler(
service, null, targetRef, null, getClient().newURIBuilder(prefixURI.toASCIIString())));
} else {
handler = OperationInvocationHandler.getInstance(EntityInvocationHandler.getInstance(
prefixURI, targetRef, service));
}
}
return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class>[] {operationRef}, handler);
} else if (isSelfMethod(method)) {
return invokeSelfMethod(method, args);
} else {
throw new NoSuchMethodException(method.getName());
}
}
public void filter(final String filter) {
if (this.uri != null) {
this.uri.filter(filter);
}
}
public void filter(final URIFilter filter) {
if (this.uri != null) {
this.uri.filter(filter);
}
}
public void orderBy(final Sort... sort) {
if (this.uri != null) {
final StringBuilder builder = new StringBuilder();
for (Sort sortClause : sort) {
builder.append(sortClause.getKey()).append(' ').append(sortClause.getValue()).append(',');
}
builder.deleteCharAt(builder.length() - 1);
this.uri.orderBy(builder.toString());
}
}
public void orderBy(final String orderBy) {
if (this.uri != null) {
this.uri.orderBy(orderBy);
}
}
public void top(final int top) throws IllegalArgumentException {
if (this.uri != null) {
this.uri.top(top);
}
}
public void skip(final int skip) throws IllegalArgumentException {
if (this.uri != null) {
this.uri.skip(skip);
}
}
public void expand(final String... expand) {
if (this.uri != null) {
this.uri.expand(expand);
}
}
public void select(final String... select) {
if (this.uri != null) {
this.uri.select(select);
}
}
public void clearQueryOptions() {
this.uri = this.baseURI == null ? null : getClient().newURIBuilder(baseURI.toASCIIString());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy