All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vmware.xenon.common.QueryResultsProcessor Maven / Gradle / Ivy

There is a newer version: 1.6.18
Show newest version
/*
 * Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
 *
 * 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.vmware.xenon.common;

import java.util.Collections;
import java.util.Objects;
import java.util.stream.Stream;

import com.google.gson.JsonObject;

import com.vmware.xenon.services.common.QueryTask;

/**
 * A thin wrapper on top of {@link QueryTask} that converts query results to service documents.
 */
public final class QueryResultsProcessor {
    private final QueryTask task;
    private final ServiceDocumentQueryResult results;

    private QueryResultsProcessor(QueryTask task, ServiceDocumentQueryResult results) {
        this.task = task;
        this.results = results;
    }

    public static QueryResultsProcessor create(QueryTask task) {
        return new QueryResultsProcessor(task, task.results);
    }

    public static QueryResultsProcessor create(ServiceDocumentQueryResult results) {
        return new QueryResultsProcessor(null, results);
    }

    /**
     * Create a QueryResultsProcessor by trying to parse the Operation body as either QueryTask or
     * ServiceDocumentQueryResult or ODataFactoryQueryResult.
     * @param op
     * @return
     * @throws IllegalArgumentException if the body is not one of the results-holding documents
     */
    public static QueryResultsProcessor create(Operation op) {
        Object rawBody = op.getBodyRaw();

        if (rawBody instanceof QueryTask) {
            QueryTask qt = (QueryTask) rawBody;
            return new QueryResultsProcessor(qt, qt.results);
        } else if (rawBody instanceof ServiceDocumentQueryResult) {
            ServiceDocumentQueryResult qr = (ServiceDocumentQueryResult) rawBody;
            return new QueryResultsProcessor(null, qr);
        } else if (rawBody instanceof String || rawBody instanceof JsonObject) {
            QueryTask maybeTask = op.getBody(QueryTask.class);

            if (Objects.equals(maybeTask.documentKind, QueryTask.KIND)) {
                return new QueryResultsProcessor(maybeTask, maybeTask.results);
            } else {
                // coerce result to only thing left that would make sense in this context
                ServiceDocumentQueryResult results = op.getBody(ServiceDocumentQueryResult.class);
                return new QueryResultsProcessor(null, results);
            }
        }

        throw new IllegalArgumentException("Cannot create QueryResultsProcessor from a " + op.getUri());
    }

    /**
     * Return the backing task, if any
     * @return
     */
    public QueryTask getQueryTask() {
        return this.task;
    }

    public boolean hasResults() {
        return this.results != null && this.results.documentCount != null && this.results.documentCount > 0;
    }

    /**
     * Streams results by coercing documents to the given type.
     * @param type
     * @param 
     * @return
     */
    public  Stream streamDocuments(Class type) {
        if (this.results == null || this.results.documents == null) {
            return Collections.emptyList().stream();
        }

        return this.results.documents
                .values()
                .stream()
                .map(o -> convert(type, o));
    }

    /**
     * Return the backing task, if any, null otherwise
     * @return
     */
    public ServiceDocumentQueryResult getQueryResult() {
        return this.results;
    }

    /**
     * Returns a selected document doing any conversion if needed.
     *
     * @param selfLink
     * @param type
     * @param 
     * @return
     */
    public  T selectedDocument(String selfLink, Class type) {
        if (this.results == null || this.results.selectedDocuments == null) {
            return null;
        }

        Object o = this.results.selectedDocuments.get(selfLink);
        return convert(type, o);
    }

    /**
     * Return a results for a selfLink optionally converting it to desired typed.
     * @param selfLink
     * @param type
     * @param 
     * @return
     */
    public  T document(String selfLink, Class type) {
        if (this.results == null || this.results.documents == null) {
            return null;
        }
        Object o = this.results.documents.get(selfLink);
        return convert(type, o);
    }

    /**
     * Iterate over all selected documents converted to the desired type. The returned iterable is
     * not reusable.
     * @param type
     * @param 
     * @return
     */
    public  Iterable selectedDocuments(Class type) {
        if (this.results == null || this.results.selectedDocuments == null) {
            return Collections.emptyList();
        }

        Stream stream = this.results.selectedDocuments
                .values()
                .stream()
                .map(o -> convert(type, o));

        return stream::iterator;
    }

    public Iterable selectedLinks() {
        if (this.results == null || this.results.selectedLinks == null) {
            return Collections.emptyList();
        }

        return this.results.selectedLinks;
    }

    public Iterable documentLinks() {
        if (this.results == null || this.results.documentLinks == null) {
            return Collections.emptyList();
        }

        return this.results.documentLinks;
    }

    /**
     * Iterate over documents. The returned Iterable is not reusable.
     * @param type
     * @param 
     * @return
     */
    public  Iterable documents(Class type) {
        return streamDocuments(type)::iterator;
    }

    private  T convert(Class type, Object o) {
        if (o == null) {
            return null;
        }
        if (type.isInstance(o)) {
            return type.cast(o);
        } else if (o instanceof String || o instanceof JsonObject) {
            // assume json serialized string
            return Utils.fromJson(o, type);
        } else {
            throw new IllegalArgumentException(
                    String.format("Cannot convert %s to %s", o.getClass().getName(),
                            type.getName()));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy