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