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

com.datastax.stargate.sdk.doc.DocumentClient Maven / Gradle / Ivy

There is a newer version: 2.3.7
Show newest version
/*
 * Copyright DataStax, Inc.
 *
 * 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.datastax.stargate.sdk.doc;

import static com.datastax.stargate.sdk.utils.JsonUtils.marshall;
import static com.datastax.stargate.sdk.utils.JsonUtils.unmarshallBean;

import java.net.HttpURLConnection;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

import com.datastax.stargate.sdk.StargateClientNode;
import com.datastax.stargate.sdk.StargateHttpClient;
import com.datastax.stargate.sdk.core.ApiResponseHttp;
import com.datastax.stargate.sdk.utils.Assert;
import com.datastax.stargate.sdk.utils.JsonUtils;

/**
 * Part of the Document API in stargate wrapper for methods at the document level.
 *
 * @author Cedrick LUNVEN (@clunven)
 */
public class DocumentClient {
    
    /** Get Topology of the nodes. */
    private final StargateHttpClient stargateHttpClient;
    
    /** Namespace. */
    private CollectionClient collectionClient;
    
    /** Unique document identifer. */
    private String docId;
    
    /**
     * Full constructor.
     * 
     * @param stargateHttpClient stargateHttpClient
     * @param collectionClient CollectionClient
     * @param docId String
     */
    public DocumentClient(StargateHttpClient stargateHttpClient, CollectionClient collectionClient, String docId) {
        this.collectionClient   = collectionClient;
        this.docId              = docId;
        this.stargateHttpClient = stargateHttpClient;
    }
    
    /**
     * Leverage find() to check existence without eventual formatting issues. 
     * https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/getDocById
     * 
     * @return boolean
     */
    public boolean exist() {
        return HttpURLConnection.HTTP_OK == stargateHttpClient.GET(documentResource).getCode();
    }
    
    /**
     * Replace a document. https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/replaceDoc
     * 
     * @param  working class
     * @param doc DOC
     * @return DOC
     */
    public  String upsert(DOC doc) {
        Assert.notNull(doc, "document");
        ApiResponseHttp res = stargateHttpClient.PUT(documentResource, marshall(doc));
        return marshallDocumentId(res.getBody());
    }
  
    /**
     * Update part of a document. https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/updatePartOfDoc
     * 
     * @param  working class
     * @param doc working class
     * @return DOC
     */
    public  String update(DOC doc) {
        Assert.notNull(doc, "document");
        ApiResponseHttp res = stargateHttpClient.PATCH(documentResource, marshall(doc));
        return marshallDocumentId(res.getBody());
    }
    
    /**
     * Get a document by {document-id}. https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/getDocById
     *
     * @param  working class
     * @param clazz working class
     * @return a document if exist
     */
    public  Optional find(Class clazz) {
        Assert.notNull(clazz, "className");
        ApiResponseHttp res = stargateHttpClient.GET(documentResource, "?raw=true");
        if (HttpURLConnection.HTTP_OK == res.getCode()) {
           return Optional.of(marshallDocument(res.getBody(), clazz));
        }
        if (HttpURLConnection.HTTP_NOT_FOUND == res.getCode()) {
            return Optional.empty();
        }
        return Optional.empty();
    }

    /**
     * Delete a document. https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/deleteDoc
     */
    public void delete() {
        if (!exist()) {
            throw new IllegalArgumentException("Cannot delete " + docId + ", it does not exists");
        }
        stargateHttpClient.DELETE(documentResource);
    }
    
    /**
     * Add '/' if needed.
     * 
     * @param path
     *      current path
     * @return
     *      path with '/'
     */
    private String formatPath(String path) {
        Assert.hasLength(path, "hasLength");
        if (!path.startsWith("/")) {
            path = "/" + path;
        }
        return path;
    }
    
    /**
     * Get a sub document by {document-path}.
     * https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/GetSubDocByPath
     *
     * @param  working class
     * @param path subpath in the doc
     * @param className  working class
     * @return SUBDOC
     */
    public  Optional findSubDocument(String path, Class className) {
        Assert.notNull(className, "expectedClass");
        ApiResponseHttp res = stargateHttpClient.GET(documentResource, formatPath(path) + "?raw=true");
        if (HttpURLConnection.HTTP_OK == res.getCode()) {
           return Optional.of(marshallDocument(res.getBody(), className));
        }
        if (HttpURLConnection.HTTP_NOT_FOUND == res.getCode()) {
            return Optional.empty();
        }
        return Optional.empty();
    }
    
    /**
     * Execute a function on a document.
     * @param path
     *      current document sub path
     * @param function
     *      function executed.
     * @param value
     *      value for attribute to update
     * @return
     *      attribute updated
     */
    @SuppressWarnings("unchecked")
    public String executefunction(String path, String function, Object value) {
        if (value instanceof String) { 
            value = "\"" + value + "\"";
        }
        ApiResponseHttp res = stargateHttpClient.POST(documentResource, 
                "{ \"operation\":\"" + function + "\",\"value\":" + JsonUtils.marshall(value) + "}", 
                formatPath(path) + "/function");
        // Parse result
        Map doc = unmarshallBean(res.getBody(), Map.class);
        if (doc.containsKey("data")) {
            return marshall(doc.get("data"));
        }
        return res.getBody();
    }
    
    /**
     * Replace a subpart of the document.
     * https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/replaceSubDoc
     * 
     * @param  working class
     * @param path subpath in the doc
     * @param newValue object for the new value
     */
    public  void replaceSubDocument(String path, SUBDOC newValue) {
        Assert.notNull(newValue, "newValue");
        stargateHttpClient.PUT(documentResource, marshall(newValue), formatPath(path));
    }
    
    /**
     * Update part of a sub document
     * https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/updatePartOfSubDoc
     * 
     * @param  working class
     * @param path subpath in the doc
     * @param newValue object for the new value
     */
    public  void updateSubDocument(String path, SUBDOC newValue) {
        Assert.notNull(newValue, "newValue");
        stargateHttpClient.PATCH(documentResource, marshall(newValue), formatPath(path));
    }
    
    /**
     * Delete a sub document.
     * https://docs.datastax.com/en/astra/docs/_attachments/docv2.html#operation/deleteSubDoc
     * 
     * @param path sub document path
     */
    public void deleteSubDocument(String path) {
        stargateHttpClient.DELETE(documentResource, formatPath(path) + "?raw=true");
    }
    
    /**
     * marshallDocumentId
     * 
     * @param body String
     * @return String
     */
    private String marshallDocumentId(String body) {
        try {
            return (String) unmarshallBean(body, Map.class).get(CollectionClient.DOCUMENT_ID);
        } catch (Exception e) {
            throw new RuntimeException("Cannot marshall document after 'upsert'", e);
        }
    }
    
    // ---------------------------------
    // ----       Resources         ----
    // ---------------------------------    
    
    /**
     * marshallDocument
     * 
     * @param  DOC
     * @param body String
     * @param clazz DOC
     * @return DOC
     */
    @SuppressWarnings("unchecked")
    private  SUBDOC marshallDocument(String body,  Class clazz) {
        try {
            if (clazz.equals(String.class)) {
               return (SUBDOC) body;
            }
            return unmarshallBean(body, clazz);
        } catch (Exception e) {
            throw new RuntimeException("Cannot marshal output '" + body + "' into class '"+ clazz +"'", e);
        }
    }
    
    /** 
     * /v2/schemas/namespaces/{namespace}/collections/{collection}/{docId} 
     */
    public Function documentResource = 
            (node) -> collectionClient.collectionResource.apply(node) +  "/" + docId;
       
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy