org.apache.olingo.ext.proxy.commons.EntitySetInvocationHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.olingo.ext.proxy.commons.EntitySetInvocationHandler.java

Source

/*
 * 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);
    }
}