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 021package org.granite.messaging.jmf.codec.std.impl; 022 023import java.io.IOException; 024import java.io.OutputStream; 025 026import org.granite.messaging.jmf.CodecRegistry; 027import org.granite.messaging.jmf.DumpContext; 028import org.granite.messaging.jmf.InputContext; 029import org.granite.messaging.jmf.OutputContext; 030import org.granite.messaging.jmf.codec.std.EnumCodec; 031 032/** 033 * @author Franck WOLFF 034 */ 035public 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}