001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2013 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.messaging.jmf.codec.std.impl;
022
023 import java.io.IOException;
024 import java.io.OutputStream;
025
026 import org.granite.messaging.jmf.CodecRegistry;
027 import org.granite.messaging.jmf.DumpContext;
028 import org.granite.messaging.jmf.InputContext;
029 import org.granite.messaging.jmf.OutputContext;
030 import org.granite.messaging.jmf.codec.std.EnumCodec;
031
032 /**
033 * @author Franck WOLFF
034 */
035 public class EnumCodecImpl extends AbstractIntegerStringCodec<Object> implements EnumCodec {
036
037 protected static final StringTypeHandler TYPE_HANDLER = new StringTypeHandler() {
038
039 public int type(IntegerComponents ics, boolean reference) {
040 return (reference ? (0x40 | (ics.length << 4) | JMF_ENUM) : ((ics.length << 4) | JMF_ENUM));
041 }
042
043 public int indexOrLengthBytesCount(int parameterizedJmfType) {
044 return (parameterizedJmfType >> 4) & 0x03;
045 }
046
047 public boolean isReference(int parameterizedJmfType) {
048 return (parameterizedJmfType & 0x40) != 0;
049 }
050 };
051
052 public int getObjectType() {
053 return JMF_ENUM;
054 }
055
056 public boolean canEncode(Object v) {
057 return v.getClass().isEnum();
058 }
059
060 public void encode(OutputContext ctx, Object v) throws IOException {
061 final OutputStream os = ctx.getOutputStream();
062
063 int indexOfStoredObject = ctx.indexOfStoredObjects(v);
064 if (indexOfStoredObject >= 0) {
065 IntegerComponents ics = intComponents(indexOfStoredObject);
066 os.write(0x80 | (ics.length << 4) | JMF_ENUM);
067 writeIntData(ctx, ics);
068 }
069 else {
070 ctx.addToStoredObjects(v);
071
072 String className = ctx.getAlias(v.getClass().getName());
073 writeString(ctx, className, TYPE_HANDLER);
074
075 int ordinal = ((Enum<?>)v).ordinal();
076 ctx.getSharedContext().getCodecRegistry().getIntegerCodec().writeVariableInt(ctx, ordinal);
077 }
078 }
079
080 public Object decode(InputContext ctx, int parameterizedJmfType) throws IOException, ClassNotFoundException {
081 final CodecRegistry codecRegistry = ctx.getSharedContext().getCodecRegistry();
082
083 int jmfType = codecRegistry.extractJmfType(parameterizedJmfType);
084
085 if (jmfType != JMF_ENUM)
086 throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
087
088 int indexOrLength = readIntData(ctx, (parameterizedJmfType >> 4) & 0x03, false);
089
090 Object v = null;
091 if ((parameterizedJmfType & 0x80) != 0)
092 v = ctx.getSharedObject(indexOrLength);
093 else {
094 String className = readString(ctx, parameterizedJmfType, indexOrLength, TYPE_HANDLER);
095 className = ctx.getAlias(className);
096 Class<?> cls = ctx.getSharedContext().getReflection().loadClass(className);
097
098 int ordinal = codecRegistry.getIntegerCodec().readVariableInt(ctx);
099
100 v = cls.getEnumConstants()[ordinal];
101 ctx.addSharedObject(v);
102 }
103
104 return v;
105 }
106
107 public void dump(DumpContext ctx, int parameterizedJmfType) throws IOException {
108 final CodecRegistry codecRegistry = ctx.getSharedContext().getCodecRegistry();
109
110 int jmfType = codecRegistry.extractJmfType(parameterizedJmfType);
111
112 if (jmfType != JMF_ENUM)
113 throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
114
115 int indexOrLength = readIntData(ctx, (parameterizedJmfType >> 4) & 0x03, false);
116 if ((parameterizedJmfType & 0x80) != 0) {
117 String className = (String)ctx.getSharedObject(indexOrLength);
118 ctx.indentPrintLn("<" + className + "@" + indexOrLength + ">");
119 }
120 else {
121 String className = readString(ctx, parameterizedJmfType, indexOrLength, TYPE_HANDLER);
122 className = ctx.getAlias(className);
123 int ordinal = codecRegistry.getIntegerCodec().readVariableInt(ctx);
124
125 int indexOfStoredObject = ctx.addSharedObject(className);
126 ctx.indentPrintLn(className + "@" + indexOfStoredObject + ": <" + ordinal + ">");
127 }
128 }
129 }