/* * Copyright 2015 Couchbase, 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 org.couchbase.mock.memcached.protocol; import org.couchbase.mock.subdoc.Operation; import java.net.ProtocolException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; public abstract class BinarySubdocMultiCommand extends BinaryCommand { private int expiryTime; private boolean hasExpiry; private byte docFlags; protected final List<MultiSpec> specs = new ArrayList<MultiSpec>(); public BinarySubdocMultiCommand(ByteBuffer header) throws ProtocolException { super(header); } @Override public void process() throws ProtocolException { bodyBuffer.rewind(); switch (extraLength) { case 0: expiryTime = 0; docFlags = 0; hasExpiry = false; break; case 1: expiryTime = 0; hasExpiry = false; docFlags = bodyBuffer.get(0); break; case 4: expiryTime = bodyBuffer.getInt(0); hasExpiry = true; docFlags = 0; break; case 5: expiryTime = bodyBuffer.getInt(0); hasExpiry = true; docFlags = bodyBuffer.get(4); break; default: throw new ProtocolException("Extras must be 0, 1, 4, or 5!"); } try { bodyBuffer.position(extraLength + keyLength); extractSpecs(); } finally { bodyBuffer.rewind(); } if (specs.isEmpty()) { throw new ProtocolException("Found no specs!"); } } protected abstract void extractSpecs() throws ProtocolException; public List<MultiSpec> getLookupSpecs() { return specs; } public int getNewExpiry(int oldExpiry) { if (hasExpiry) { return expiryTime; } else { return oldExpiry; } } public byte getSubdocDocFlags() { return docFlags; } public static class MultiSpec { final private Operation op; final private String path; final private String value; final private byte flags; protected MultiSpec(Operation op, String path, String value, byte flags) { this.op = op; this.path = path; this.flags = flags; this.value = value; } protected MultiSpec(Operation op, String path) { this(op, path, null, (byte)0); } public Operation getOp() { return op; } public String getPath() { return path; } public String getValue() { return value; } public byte getFlags() { return flags; } } }