/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.zookeeper; import org.apache.jute.InputArchive; import org.apache.jute.OutputArchive; import org.apache.jute.Record; import org.apache.zookeeper.proto.CreateResponse; import org.apache.zookeeper.proto.MultiHeader; import org.apache.zookeeper.proto.SetDataResponse; import org.apache.zookeeper.proto.ErrorResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Handles the response from a multi request. Such a response consists of * a sequence of responses each prefixed by a MultiResponse that indicates * the type of the response. The end of the list is indicated by a MultiHeader * with a negative type. Each individual response is in the same format as * with the corresponding operation in the original request list. */ public class MultiResponse implements Record, Iterable<OpResult> { private List<OpResult> results = new ArrayList<OpResult>(); public void add(OpResult x) { results.add(x); } @Override public Iterator<OpResult> iterator() { return results.iterator(); } public int size() { return results.size(); } @Override public void serialize(OutputArchive archive, String tag) throws IOException { archive.startRecord(this, tag); int index = 0; for (OpResult result : results) { int err = result.getType() == ZooDefs.OpCode.error ? ((OpResult.ErrorResult)result).getErr() : 0; new MultiHeader(result.getType(), false, err).serialize(archive, tag); switch (result.getType()) { case ZooDefs.OpCode.create: new CreateResponse(((OpResult.CreateResult) result).getPath()).serialize(archive, tag); break; case ZooDefs.OpCode.delete: case ZooDefs.OpCode.check: break; case ZooDefs.OpCode.setData: new SetDataResponse(((OpResult.SetDataResult) result).getStat()).serialize(archive, tag); break; case ZooDefs.OpCode.error: new ErrorResponse(((OpResult.ErrorResult) result).getErr()).serialize(archive, tag); break; default: throw new IOException("Invalid type " + result.getType() + " in MultiResponse"); } } new MultiHeader(-1, true, -1).serialize(archive, tag); archive.endRecord(this, tag); } @Override public void deserialize(InputArchive archive, String tag) throws IOException { results = new ArrayList<OpResult>(); archive.startRecord(tag); MultiHeader h = new MultiHeader(); h.deserialize(archive, tag); while (!h.getDone()) { switch (h.getType()) { case ZooDefs.OpCode.create: CreateResponse cr = new CreateResponse(); cr.deserialize(archive, tag); results.add(new OpResult.CreateResult(cr.getPath())); break; case ZooDefs.OpCode.delete: results.add(new OpResult.DeleteResult()); break; case ZooDefs.OpCode.setData: SetDataResponse sdr = new SetDataResponse(); sdr.deserialize(archive, tag); results.add(new OpResult.SetDataResult(sdr.getStat())); break; case ZooDefs.OpCode.check: results.add(new OpResult.CheckResult()); break; case ZooDefs.OpCode.error: //FIXME: need way to more cleanly serialize/deserialize exceptions ErrorResponse er = new ErrorResponse(); er.deserialize(archive, tag); results.add(new OpResult.ErrorResult(er.getErr())); break; default: throw new IOException("Invalid type " + h.getType() + " in MultiResponse"); } h.deserialize(archive, tag); } archive.endRecord(tag); } public List<OpResult> getResultList() { return results; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof MultiResponse)) return false; MultiResponse other = (MultiResponse) o; if (results != null) { Iterator<OpResult> i = other.results.iterator(); for (OpResult result : results) { if (i.hasNext()) { if (!result.equals(i.next())) { return false; } } else { return false; } } return !i.hasNext(); } else return other.results == null; } @Override public int hashCode() { int hash = results.size(); for (OpResult result : results) { hash = (hash * 35) + result.hashCode(); } return hash; } }