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; 025import java.util.HashMap; 026import java.util.Map; 027 028import org.granite.messaging.jmf.CodecRegistry; 029import org.granite.messaging.jmf.DumpContext; 030import org.granite.messaging.jmf.InputContext; 031import org.granite.messaging.jmf.JMFEncodingException; 032import org.granite.messaging.jmf.OutputContext; 033import org.granite.messaging.jmf.codec.StandardCodec; 034import org.granite.messaging.jmf.codec.std.HashMapCodec; 035 036/** 037 * @author Franck WOLFF 038 */ 039public 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}