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 import java.util.HashMap;
026 import java.util.Map;
027
028 import org.granite.messaging.jmf.CodecRegistry;
029 import org.granite.messaging.jmf.DumpContext;
030 import org.granite.messaging.jmf.InputContext;
031 import org.granite.messaging.jmf.JMFEncodingException;
032 import org.granite.messaging.jmf.OutputContext;
033 import org.granite.messaging.jmf.codec.StandardCodec;
034 import org.granite.messaging.jmf.codec.std.HashMapCodec;
035
036 /**
037 * @author Franck WOLFF
038 */
039 public class HashMapCodecImpl extends AbstractIntegerStringCodec<HashMap<?, ?>> implements HashMapCodec {
040
041 public int getObjectType() {
042 return JMF_HASH_MAP;
043 }
044
045 public Class<?> getObjectClass() {
046 return HashMap.class;
047 }
048
049 public void encode(OutputContext ctx, HashMap<?, ?> v) throws IOException {
050 final OutputStream os = ctx.getOutputStream();
051
052 int indexOfStoredObject = ctx.indexOfStoredObjects(v);
053 if (indexOfStoredObject >= 0) {
054 IntegerComponents ics = intComponents(indexOfStoredObject);
055 os.write(0x80 | (ics.length << 5) | JMF_HASH_MAP);
056 writeIntData(ctx, ics);
057 }
058 else {
059 ctx.addToStoredObjects(v);
060
061 Map.Entry<?, ?>[] snapshot = v.entrySet().toArray(new Map.Entry<?, ?>[0]);
062
063 IntegerComponents ics = intComponents(snapshot.length);
064 os.write((ics.length << 5) | JMF_HASH_MAP);
065 writeIntData(ctx, ics);
066
067 for (Map.Entry<?, ?> entry : snapshot) {
068 ctx.writeObject(entry.getKey());
069 ctx.writeObject(entry.getValue());
070 }
071 }
072 }
073
074 public HashMap<?, ?> decode(InputContext ctx, int parameterizedJmfType) throws IOException, ClassNotFoundException {
075 int jmfType = ctx.getSharedContext().getCodecRegistry().extractJmfType(parameterizedJmfType);
076
077 if (jmfType != JMF_HASH_MAP)
078 throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
079
080 final int indexOrLength = readIntData(ctx, (parameterizedJmfType >> 5) & 0x03, false);
081 if ((parameterizedJmfType & 0x80) != 0)
082 return (HashMap<?, ?>)ctx.getSharedObject(indexOrLength);
083
084 HashMap<Object, Object> v = new HashMap<Object, Object>(indexOrLength);
085 ctx.addSharedObject(v);
086
087 for (int index = 0; index < indexOrLength; index++) {
088 Object key = ctx.readObject();
089 Object value = ctx.readObject();
090 v.put(key, value);
091 }
092
093 return v;
094 }
095
096 public void dump(DumpContext ctx, int parameterizedJmfType) throws IOException {
097 final CodecRegistry codecRegistry = ctx.getSharedContext().getCodecRegistry();
098
099 int jmfType = codecRegistry.extractJmfType(parameterizedJmfType);
100
101 if (jmfType != JMF_HASH_MAP)
102 throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
103
104 int indexOrLength = readIntData(ctx, (parameterizedJmfType >> 5) & 0x03, false);
105 if ((parameterizedJmfType & 0x80) != 0) {
106 String v = (String)ctx.getSharedObject(indexOrLength);
107 ctx.indentPrintLn("<" + v + "@" + indexOrLength + ">");
108 return;
109 }
110
111 String v = HashMap.class.getName() + "[" + indexOrLength + "]";
112 int indexOfStoredObject = ctx.addSharedObject(v);
113 ctx.indentPrintLn(v + "@" + indexOfStoredObject + " {");
114 ctx.incrIndent(1);
115
116 for (int index = 0; index < indexOrLength; index++) {
117 parameterizedJmfType = ctx.safeRead();
118 jmfType = codecRegistry.extractJmfType(parameterizedJmfType);
119 StandardCodec<?> codec = codecRegistry.getCodec(jmfType);
120
121 if (codec == null)
122 throw new JMFEncodingException("No codec for JMF type: " + jmfType);
123
124 codec.dump(ctx, parameterizedJmfType);
125
126 ctx.incrIndent(1);
127 parameterizedJmfType = ctx.safeRead();
128 jmfType = codecRegistry.extractJmfType(parameterizedJmfType);
129 codec = codecRegistry.getCodec(jmfType);
130
131 if (codec == null)
132 throw new JMFEncodingException("No codec for JMF type: " + jmfType);
133
134 codec.dump(ctx, parameterizedJmfType);
135 ctx.incrIndent(-1);
136 }
137
138 ctx.incrIndent(-1);
139 ctx.indentPrintLn("}");
140 }
141 }