com.marklogic.xcc.impl.RequestImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of marklogic-xcc Show documentation
Show all versions of marklogic-xcc Show documentation
MarkLogic XML Contentbase Connector for Java (XCC/J)
/*
* 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;
}
}