| /* |
| * 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.io.Serializable; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Proxy; |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.Future; |
| |
| import org.apache.commons.lang3.tuple.Triple; |
| import org.apache.olingo.client.api.communication.request.retrieve.ODataValueRequest; |
| import org.apache.olingo.client.api.domain.ClientAnnotation; |
| import org.apache.olingo.client.api.domain.ClientEntity; |
| import org.apache.olingo.client.api.uri.URIBuilder; |
| import org.apache.olingo.commons.api.edm.FullQualifiedName; |
| import org.apache.olingo.commons.api.format.ContentType; |
| import org.apache.olingo.ext.proxy.AbstractService; |
| import org.apache.olingo.ext.proxy.api.AbstractEntitySet; |
| import org.apache.olingo.ext.proxy.api.AbstractSingleton; |
| import org.apache.olingo.ext.proxy.api.EntityCollection; |
| import org.apache.olingo.ext.proxy.api.EntityType; |
| import org.apache.olingo.ext.proxy.api.Search; |
| import org.apache.olingo.ext.proxy.api.StructuredType; |
| import org.apache.olingo.ext.proxy.api.annotations.Namespace; |
| import org.apache.olingo.ext.proxy.context.AttachedEntityStatus; |
| import org.apache.olingo.ext.proxy.context.EntityContext; |
| import org.apache.olingo.ext.proxy.context.EntityUUID; |
| import org.apache.olingo.ext.proxy.utils.ClassUtils; |
| |
| public class EntitySetInvocationHandler< |
| T extends EntityType<?>, KEY extends Serializable, EC extends EntityCollection<T, ?, ?>> |
| extends AbstractEntityCollectionInvocationHandler<T, EC> |
| implements AbstractEntitySet<T, KEY, EC> { |
| |
| private static final long serialVersionUID = 2629912294765040027L; |
| |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| public static EntitySetInvocationHandler getInstance(final Class<?> ref, final AbstractService<?> service) { |
| return new EntitySetInvocationHandler(ref, service, buildEntitySetURI(ref, service)); |
| } |
| |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| public static EntitySetInvocationHandler getInstance( |
| final Class<?> ref, final AbstractService<?> service, final URI uri) { |
| return new EntitySetInvocationHandler(ref, service, service.getClient().newURIBuilder(uri.toASCIIString())); |
| } |
| |
| protected EntitySetInvocationHandler( |
| final Class<?> ref, |
| final AbstractService<?> service, |
| final URIBuilder uri) { |
| |
| super(ref, service, uri); |
| } |
| |
| @Override |
| public Object invoke(final Object proxy, final Method method, final 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 (isSelfMethod(method)) { |
| return invokeSelfMethod(method, args); |
| } else { |
| throw new NoSuchMethodException(method.getName()); |
| } |
| } |
| |
| @Override |
| public Long count() { |
| final ODataValueRequest req = getClient().getRetrieveRequestFactory(). |
| getValueRequest(getClient().newURIBuilder(this.uri.build().toASCIIString()).count().build()); |
| req.setFormat(ContentType.TEXT_PLAIN); |
| return Long.valueOf(req.execute().getBody().asPrimitive().toString()); |
| } |
| |
| @Override |
| public Boolean exists(final KEY key) throws IllegalArgumentException { |
| try { |
| StructuredType.class.cast(getByKey(key)).load(); |
| return true; |
| } catch (Exception e) { |
| LOG.error("Could not check existence of {}({})", this.uri, key, e); |
| return false; |
| } |
| } |
| |
| @Override |
| public T getByKey(final KEY key) throws IllegalArgumentException { |
| return getByKey(key, itemRef); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public <S extends T> S getByKey(final KEY key, final Class<S> typeRef) throws IllegalArgumentException { |
| if (key == null) { |
| throw new IllegalArgumentException("Null key"); |
| } |
| |
| final EntityUUID uuid = new EntityUUID(this.baseURI, typeRef, key); |
| LOG.debug("Ask for '{}({})'", typeRef.getSimpleName(), key); |
| |
| EntityInvocationHandler handler = getContext().entityContext().getEntity(uuid); |
| |
| if (handler == null) { |
| final ClientEntity entity = getClient().getObjectFactory().newEntity(new FullQualifiedName( |
| typeRef.getAnnotation(Namespace.class).value(), ClassUtils.getEntityTypeName(typeRef))); |
| |
| handler = EntityInvocationHandler.getInstance(key, entity, this.baseURI, typeRef, service); |
| } |
| |
| if (isDeleted(handler)) { |
| // object deleted |
| LOG.debug("Object '{}({})' has been deleted", typeRef.getSimpleName(), uuid); |
| return null; |
| } else { |
| // clear query options |
| handler.clearQueryOptions(); |
| return (S) Proxy.newProxyInstance( |
| Thread.currentThread().getContextClassLoader(), |
| new Class<?>[] {typeRef}, |
| handler); |
| } |
| } |
| |
| @Override |
| public EC execute() { |
| return execute(collItemRef); |
| } |
| |
| public <S extends T, SEC extends EntityCollection<S, ?, ?>> Future<SEC> executeAsync(final Class<SEC> collTypeRef) { |
| return service.getClient().getConfiguration().getExecutor().submit(new Callable<SEC>() { |
| @Override |
| public SEC call() throws Exception { |
| return execute(collTypeRef); |
| } |
| }); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public <S extends T, SEC extends EntityCollection<S, ?, ?>> SEC execute(final Class<SEC> collTypeRef) { |
| final Class<S> ref = (Class<S>) ClassUtils.extractTypeArg(collTypeRef, |
| AbstractEntitySet.class, AbstractSingleton.class, EntityCollection.class); |
| final Class<S> oref = (Class<S>) ClassUtils.extractTypeArg(this.collItemRef, |
| AbstractEntitySet.class, AbstractSingleton.class, EntityCollection.class); |
| |
| |
| if (!oref.equals(ref)) { |
| uri.appendDerivedEntityTypeSegment(new FullQualifiedName( |
| ClassUtils.getNamespace(ref), ClassUtils.getEntityTypeName(ref)).toString()); |
| } |
| |
| final List<ClientAnnotation> anns = new ArrayList<ClientAnnotation>(); |
| |
| final Triple<List<T>, URI, List<ClientAnnotation>> entitySet = fetchPartial(uri.build(), (Class<T>) ref); |
| anns.addAll(entitySet.getRight()); |
| |
| final EntityCollectionInvocationHandler<S> entityCollectionHandler = new EntityCollectionInvocationHandler<S>( |
| service, (List<S>) entitySet.getLeft(), collTypeRef, this.baseURI, uri); |
| entityCollectionHandler.setAnnotations(anns); |
| |
| entityCollectionHandler.nextPageURI = entitySet.getMiddle(); |
| |
| return (SEC) Proxy.newProxyInstance( |
| Thread.currentThread().getContextClassLoader(), |
| new Class<?>[] {collTypeRef}, |
| entityCollectionHandler); |
| } |
| |
| @Override |
| public Search<T, EC> createSearch() { |
| return new SearchImpl<T, EC>(getClient(), this.collItemRef, this.baseURI, this); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public <S extends T, SEC extends EntityCollection<S, ?, ?>> Search<S, SEC> createSearch(final Class<SEC> reference) { |
| return new SearchImpl<S, SEC>( |
| getClient(), |
| reference, |
| baseURI, |
| (EntitySetInvocationHandler<S, ?, SEC>) this); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public <S extends T, SEC extends EntityCollection<S, ?, ?>> SEC fetchWholeEntitySet( |
| final URIBuilder uriBuilder, final Class<S> typeRef, final Class<SEC> collTypeRef) { |
| |
| final List<S> res = new ArrayList<S>(); |
| final List<ClientAnnotation> anns = new ArrayList<ClientAnnotation>(); |
| |
| URI nextURI = uriBuilder.build(); |
| while (nextURI != null) { |
| final Triple<List<T>, URI, List<ClientAnnotation>> entitySet = fetchPartial(nextURI, (Class<T>) typeRef); |
| res.addAll((List<S>) entitySet.getLeft()); |
| nextURI = entitySet.getMiddle(); |
| anns.addAll(entitySet.getRight()); |
| } |
| |
| final EntityCollectionInvocationHandler<S> entityCollectionHandler = |
| new EntityCollectionInvocationHandler<S>(service, res, collTypeRef, targetEntitySetURI, uriBuilder); |
| entityCollectionHandler.setAnnotations(anns); |
| |
| return (SEC) Proxy.newProxyInstance( |
| Thread.currentThread().getContextClassLoader(), |
| new Class<?>[] {collTypeRef}, |
| entityCollectionHandler); |
| } |
| |
| @Override |
| public void delete(final KEY key) throws IllegalArgumentException { |
| final EntityContext entityContext = getContext().entityContext(); |
| |
| EntityInvocationHandler entity = entityContext.getEntity(new EntityUUID(baseURI, itemRef, key)); |
| |
| if (entity == null) { |
| // search for entity |
| final T searched = getByKey(key); |
| entity = (EntityInvocationHandler) Proxy.getInvocationHandler(searched); |
| entityContext.attach(entity, AttachedEntityStatus.DELETED); |
| } else { |
| entityContext.setStatus(entity, AttachedEntityStatus.DELETED); |
| } |
| } |
| |
| @Override |
| public <S extends T> void delete(final S entity) { |
| deleteEntity((EntityInvocationHandler) Proxy.getInvocationHandler(entity), this.baseURI); |
| } |
| |
| @Override |
| public <S extends T> void delete(final Iterable<S> entities) { |
| for (S en : entities) { |
| delete(en); |
| } |
| } |
| |
| @Override |
| public EntitySetIterator<T, KEY, EC> iterator() { |
| return new EntitySetIterator<T, KEY, EC>(getClient().newURIBuilder(this.uri.build().toASCIIString()).build(), this); |
| } |
| } |