/*
* Copyright (C) 2009 JavaRosa
*
* 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.openrosa.client.jr.core.util.externalizable;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import org.openrosa.client.java.io.DataInputStream;
import org.openrosa.client.java.io.DataOutputStream;
public class ExtWrapTagged extends ExternalizableWrapper {
public final static byte[] WRAPPER_TAG = {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}; //must be same length as PrototypeFactory.CLASS_HASH_SIZE
public static HashMap WRAPPER_CODES;
static {
WRAPPER_CODES = new HashMap();
WRAPPER_CODES.put(ExtWrapNullable.class, new Integer(0x00));
WRAPPER_CODES.put(ExtWrapList.class, new Integer(0x20));
WRAPPER_CODES.put(ExtWrapListPoly.class, new Integer(0x21));
WRAPPER_CODES.put(ExtWrapMap.class, new Integer(0x22));
WRAPPER_CODES.put(ExtWrapMapPoly.class, new Integer(0x23));
WRAPPER_CODES.put(ExtWrapIntEncodingUniform.class, new Integer(0x40));
WRAPPER_CODES.put(ExtWrapIntEncodingSmall.class, new Integer(0x41));
}
/* serialization */
public ExtWrapTagged (Object val) {
if (val == null) {
throw new NullPointerException();
} else if (val instanceof ExtWrapTagged) {
throw new IllegalArgumentException("Wrapping tagged with tagged is redundant");
}
this.val = val;
}
/* deserialization */
public ExtWrapTagged () {
}
public ExternalizableWrapper clone (Object val) {
return new ExtWrapTagged(val);
}
public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException {
ExternalizableWrapper type = readTag(in, pf);
val = ExtUtil.read(in, type, pf);
}
public void writeExternal(DataOutputStream out) throws IOException {
writeTag(out, val);
ExtUtil.write(out, val);
}
public static ExternalizableWrapper readTag (DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException {
byte[] tag = new byte[PrototypeFactory.CLASS_HASH_SIZE];
in.read(tag, 0, tag.length);
if (PrototypeFactory.compareHash(tag, WRAPPER_TAG)) {
int wrapperCode = ExtUtil.readInt(in);
//find wrapper indicated by code
ExternalizableWrapper type = null;
for (Iterator e = WRAPPER_CODES.keySet().iterator(); e.hasNext(); ) {
Class t = (Class)e.next();
if (((Integer)WRAPPER_CODES.get(t)).intValue() == wrapperCode) {
try {
type = null; //(ExternalizableWrapper)PrototypeFactory.getInstance(t);
} catch (CannotCreateObjectException ccoe) {
throw new CannotCreateObjectException("Serious problem: cannot create built-in ExternalizableWrapper [" + t.getName() + "]");
}
}
}
if (type == null) {
throw new DeserializationException("Unrecognized ExternalizableWrapper type [" + wrapperCode + "]");
}
type.metaReadExternal(in, pf);
return type;
} else {
Class type = null; //pf.getClass(tag);
if (type == null) {
throw new DeserializationException("No datatype registered to serialization code " + ExtUtil.printBytes(tag));
}
return new ExtWrapBase(type);
}
}
public static void writeTag (DataOutputStream out, Object o) throws IOException {
if (o instanceof ExternalizableWrapper && !(o instanceof ExtWrapBase)) {
out.write(WRAPPER_TAG, 0, PrototypeFactory.CLASS_HASH_SIZE);
ExtUtil.writeNumeric(out, ((Integer)WRAPPER_CODES.get(o.getClass())).intValue());
((ExternalizableWrapper)o).metaWriteExternal(out);
} else {
Class type = null;
if (o instanceof ExtWrapBase) {
ExtWrapBase extType = (ExtWrapBase)o;
if (extType.val != null) {
o = extType.val;
} else {
type = extType.type;
}
}
if (type == null) {
type = o.getClass();
}
byte[] tag = null; //PrototypeFactory.getClassHash(type); //cache this?
out.write(tag, 0, tag.length);
}
}
public void metaReadExternal(DataInputStream in, PrototypeFactory pf) {
throw new RuntimeException("Tagged wrapper should never be tagged");
}
public void metaWriteExternal(DataOutputStream out) {
throw new RuntimeException("Tagged wrapper should never be tagged");
}
}