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