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

com.marklogic.xcc.impl.RequestImpl Maven / Gradle / Ivy

There is a newer version: 11.3.0
Show newest version
/*
 * Copyright (c) 2020 MarkLogic Corporation
 *
 * 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.marklogic.xcc.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.marklogic.io.IOHelper;
import com.marklogic.xcc.Request;
import com.marklogic.xcc.RequestOptions;
import com.marklogic.xcc.Session;
import com.marklogic.xcc.ValueFactory;
import com.marklogic.xcc.exceptions.UnimplementedFeatureException;
import com.marklogic.xcc.types.ValueType;
import com.marklogic.xcc.types.XName;
import com.marklogic.xcc.types.XdmSequence;
import com.marklogic.xcc.types.XdmValue;
import com.marklogic.xcc.types.XdmVariable;

@SuppressWarnings("deprecation")
public abstract class RequestImpl implements Request {
    public static final int VAR_LIMIT = 1024;
    private final Session session;
    private RequestOptions options;
    private Map variables = 
            new HashMap();
    private long position = 1; // beginning position of the requested subsequence
    private long count = Long.MAX_VALUE; // count of the requested subsequence
    
    // ---------------------------------------------------

    public RequestImpl(Session session, RequestOptions options) {
        this.session = session;

        setOptions(options);
    }

    // ---------------------------------------------------

    abstract void urlEncodeXQueryString(StringBuffer sb, Logger logger);

    abstract String serverPath();

    abstract String requestVar();

    // ---------------------------------------------------

    public Session getSession() {
        return (session);
    }

    public void setOptions(RequestOptions options) {
        if (options == null) {
            this.options = new RequestOptions();
        } else {
            this.options = options;
        }
    }

    public RequestOptions getOptions() {
        return options;
    }

    public RequestOptions getEffectiveOptions() {
        RequestOptions eff = new RequestOptions();
        RequestOptions req = getOptions();
        RequestOptions ses = getSession().getDefaultRequestOptions();

        eff.applyEffectiveValues(new RequestOptions[] { ses, req });

        return eff;
    }

    public void setVariable(XdmVariable variable) {
        XdmValue value = variable.getValue();

        if (value instanceof XdmSequence) {
            throw new UnimplementedFeatureException("Setting variables that are sequences is not supported");
        }
        
        // "set" implies replacing a var with the same XName, add() doesn't replace
        clearVariable(variable);
        if (1 + getVariableCount() > VAR_LIMIT) {
            throw new IllegalArgumentException("Cannot exceed " + 
                VAR_LIMIT + " external variables");
        }
        XdmVariable[] vars = new XdmVariable[1];
        vars[0] = variable;
        variables.put(variable.getName(), vars);
    }

    public XdmVariable setNewVariable(XName xname, XdmValue value) {
        XdmVariable variable = ValueFactory.newVariable(xname, value);

        setVariable(variable);

        return (variable);
    }
    
    public void setNewVariables(XName xname, XdmValue[] values) {
        clearVariables(xname);
        if (values.length + getVariableCount() > VAR_LIMIT) {
            throw new IllegalArgumentException("Cannot exceed " + 
                VAR_LIMIT + " external variables");
        }
        XdmVariable[] vars = new XdmVariable[values.length];
        for (int i = 0; i < vars.length; i++) {
            vars[i] = ValueFactory.newVariable(xname, values[i]);
        }
        if (vars.length == 0) {
            vars = new XdmVariable[1];
            vars[0] = ValueFactory.newVariable(xname, 
                    ValueFactory.newJSNull());
        }
        variables.put(xname, vars);
    }

    public XdmVariable setNewVariable(String namespace, String localname, ValueType type, Object value) {
        return setNewVariable(new XName(namespace, localname), ValueFactory.newValue(type, value));
    }
    
    public void setNewVariables(String namespace, String localname, ValueType type, Object[] values) {
        XName name = new XName(namespace, localname);
        clearVariables(name);
        if (values.length + getVariableCount() > VAR_LIMIT) {
            throw new IllegalArgumentException("Cannot exceed " + 
                VAR_LIMIT + " external variables");
        }
        XdmVariable[] vars = new XdmVariable[values.length];
        for (int i = 0; i < vars.length; i++) {
            vars[i] = ValueFactory.newVariable(name, 
                    ValueFactory.newValue(type, values[i]));
        }
        if (vars.length == 0) {
            vars = new XdmVariable[1];
            vars[0] = ValueFactory.newVariable(name, ValueFactory.newJSNull());
        }
        variables.put(name, vars);
    }

    public XdmVariable setNewVariable(String localname, ValueType type, Object value) {
        return setNewVariable(null, localname, type, value);
    }
    
    public void setNewVariables(String localname, ValueType type, Object[] values) {
        XName name = new XName(null, localname);
        clearVariables(name);
        if (values.length + getVariableCount() > VAR_LIMIT) {
            throw new IllegalArgumentException("Cannot exceed " + 
                VAR_LIMIT + " external variables");
        }
        XdmVariable[] vars = new XdmVariable[values.length];
        for (int i = 0; i < vars.length; i++) {
            vars[i] = ValueFactory.newVariable(name, 
                    ValueFactory.newValue(type, values[i]));
        }
        if (vars.length == 0) {
            vars = new XdmVariable[1];
            vars[0] = ValueFactory.newVariable(name, ValueFactory.newJSNull());
        }
        variables.put(name, vars);
    }

    public XdmVariable setNewStringVariable(String namespace, String localname, String value) {
        return setNewVariable(namespace, localname, ValueType.XS_STRING, value);
    }

    public XdmVariable setNewStringVariable(String localname, String value) {
        return setNewStringVariable(null, localname, value);
    }

    public XdmVariable setNewIntegerVariable(String namespace, String localname, long value) {
        return setNewVariable(namespace, localname, ValueType.XS_INTEGER, new Long(value));
    }

    public XdmVariable setNewIntegerVariable(String localname, long value) {
        return setNewIntegerVariable(null, localname, value);
    }

    public void clearVariable(XdmVariable variable) {
        variables.remove(variable.getName());
    }
    
    public void clearVariables(XName varName) {
        variables.remove(varName);
    }

    public void clearVariables() {
        variables.clear();
    }

    public XdmVariable[] getVariables() {
        ArrayList varList = new ArrayList();
        for (XdmVariable[] vars : variables.values()) {
            for (XdmVariable var : vars) {
                varList.add(var);
            }
        }
        XdmVariable[] vars = new XdmVariable[varList.size()];
        return varList.toArray(vars);
    }
    
    protected int getVariableCount() {
        int cnt = 0;
        for (XdmVariable[] vars : variables.values()) {
            cnt += vars.length;
        }
        return cnt;
    }

    // -----------------------------------------------------

    public long getPosition() {
        return position;
    }

    public void setPosition(long position) {
        this.position = position;
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

    String encodedQueryString(Logger logger) {
        StringBuffer sb = new StringBuffer();

        sb.append(requestVar()).append("=");
        urlEncodeXQueryString(sb, logger);

        encodeQueryOptions(sb, null);

        encodeQueryVariables(sb, logger);
        
        encodePositionRange(sb);
        
        encodeTxn(sb);

        String payload = sb.toString();

        if (logger.isLoggable(Level.FINEST)) {
            logger.finest("Eval request POST payload: '" + payload + "'");
        }

        return (payload);
    }
    
    public void encodeTxn(StringBuffer sb) {
        if (((SessionImpl)session).txnID != null) {
            sb.append("&txnid=").append(((SessionImpl)session).txnID);
        }
        if (((SessionImpl)session).isInCompatibleMode()) {
            return;
        }
        if (session.getTransactionMode() != null) {
            sb.append("&txnmode=").append(session.getTransactionMode());
        }
        if (session.getCachedTxnTimeout() != 0) {
            sb.append("&txntimelimit=").append(session.getCachedTxnTimeout());
        }
    }

    private void encodePositionRange(StringBuffer sb) {
        if (position > 1) {
            sb.append("&pos=").append(position);
        }
        if (count < Long.MAX_VALUE) {
            sb.append("&cnt=").append(count);
        }       
    }

    public void encodeQueryOptions(StringBuffer sb, RequestOptions requestOptions) {
        RequestOptions options = (requestOptions == null) ? getEffectiveOptions() : requestOptions;

        sb.append("&locale=").append(options.getLocale().toString());
        sb.append("&tzoffset=").append((options.getTimeZone().getOffset(System.currentTimeMillis())) / 1000);

        if (session.getContentBaseName() != null) {
            String dbname = session.getContentBaseName();

            if (isName(dbname)) {
                sb.append("&dbname=");
                IOHelper.urlEncodeToStringBuffer(sb, session.getContentBaseName());
            } else {
                sb.append("&dbid=").append(dbname.substring(1)); // numeric
            }
        }

        if (options.getEffectivePointInTime() != null) {
            sb.append("×tamp=").append(options.getEffectivePointInTime().toString());
        }

        if (options.getRequestName() != null) {
            sb.append("&requestname=");
            IOHelper.urlEncodeToStringBuffer(sb, options.getRequestName());
        }

        if (options.getDefaultXQueryVersion() != null) {
            sb.append("&defaultxquery=");
            IOHelper.urlEncodeToStringBuffer(sb, options.getDefaultXQueryVersion());
        }

        if (options.getRequestTimeLimit() != -1) {
            sb.append("&timelimit=").append(options.getRequestTimeLimit());
        }
    }

    private void encodeQueryVariables(StringBuffer sb, Logger logger) {
        XdmVariable[] vars = getVariables();

        for (int i = 0; i < vars.length; i++) {
            XdmVariable var = vars[i];
            XName xname = var.getName();
            XdmValue value = var.getValue();

            sb.append("&evn").append(i).append("=");
            if (xname.getNamespace() != null) {
                sb.append(xname.getNamespace());
            }

            sb.append("&evl").append(i).append("=").append(xname.getLocalname());
            sb.append("&evt").append(i).append("=");
            IOHelper.urlEncodeToStringBuffer(sb, value.getValueType().toString());
            sb.append("&evv").append(i).append("=");
            IOHelper.urlEncodeToStringBuffer(sb, value.asString());

            // TODO: Test this output
            if (logger.isLoggable(Level.FINEST)) {
                logger.finest(" ev" + i + ": " + xname.toString() + "(" + value.getValueType() + ") "
                        + value.toString());
            }
        }
    }

    protected boolean isName(String name) {
        if (name.length() == 0)
            return true;

        if (name.charAt(0) == '#')
            return false;

        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy