Java tutorial
/* * 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 java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.jute.InputArchive; import org.apache.jute.OutputArchive; import org.apache.jute.Record; import org.apache.zookeeper.proto.Create2Response; import org.apache.zookeeper.proto.CreateResponse; import org.apache.zookeeper.proto.ErrorResponse; import org.apache.zookeeper.proto.GetChildrenResponse; import org.apache.zookeeper.proto.GetDataResponse; import org.apache.zookeeper.proto.MultiHeader; import org.apache.zookeeper.proto.SetDataResponse; /** * 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); 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.create2: OpResult.CreateResult createResult = (OpResult.CreateResult) result; new Create2Response(createResult.getPath(), createResult.getStat()).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.getChildren: new GetChildrenResponse(((OpResult.GetChildrenResult) result).getChildren()).serialize(archive, tag); break; case ZooDefs.OpCode.getData: new GetDataResponse(((OpResult.GetDataResult) result).getData(), ((OpResult.GetDataResult) 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.create2: Create2Response cr2 = new Create2Response(); cr2.deserialize(archive, tag); results.add(new OpResult.CreateResult(cr2.getPath(), cr2.getStat())); 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.getChildren: GetChildrenResponse gcr = new GetChildrenResponse(); gcr.deserialize(archive, tag); results.add(new OpResult.GetChildrenResult(gcr.getChildren())); break; case ZooDefs.OpCode.getData: GetDataResponse gdr = new GetDataResponse(); gdr.deserialize(archive, tag); results.add(new OpResult.GetDataResult(gdr.getData(), gdr.getStat())); break; case ZooDefs.OpCode.error: // TODO: 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; } }