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}