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