001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.util.slicedMap; 018 019 import com.google.common.collect.ArrayListMultimap; 020 import com.google.common.collect.ImmutableMap; 021 import com.google.common.collect.Maps; 022 import com.google.common.collect.Multimap; 023 import org.jetbrains.annotations.NotNull; 024 025 import java.util.Collection; 026 import java.util.Iterator; 027 import java.util.Map; 028 029 public class SlicedMapImpl implements MutableSlicedMap { 030 031 public static SlicedMapImpl create() { 032 return new SlicedMapImpl(Maps.<SlicedMapKey<?, ?>, Object>newLinkedHashMap()); 033 } 034 035 public static SlicedMapImpl create(Map<SlicedMapKey<?, ?>, Object> map) { 036 return new SlicedMapImpl(map); 037 } 038 039 public static SlicedMapImpl create(MapSupplier mapSupplier) { 040 return new SlicedMapImpl(mapSupplier.<SlicedMapKey<?, ?>, Object>get()); 041 } 042 043 private final Map<SlicedMapKey<?, ?>, Object> map; 044 private final Multimap<WritableSlice<?, ?>, Object> collectiveSliceKeys = ArrayListMultimap.create(); 045 046 protected SlicedMapImpl(Map<SlicedMapKey<?, ?>, Object> map) { 047 this.map = map; 048 } 049 050 @Override 051 public <K, V> void put(WritableSlice<K, V> slice, K key, V value) { 052 if (!slice.check(key, value)) { 053 return; 054 } 055 056 SlicedMapKey<K, V> slicedMapKey = slice.makeKey(key); 057 RewritePolicy rewritePolicy = slice.getRewritePolicy(); 058 if (rewritePolicy.rewriteProcessingNeeded(key)) { 059 if (map.containsKey(slicedMapKey)) { 060 //noinspection unchecked 061 if (!rewritePolicy.processRewrite(slice, key, (V) map.get(slicedMapKey), value)) { 062 return; 063 } 064 } 065 } 066 067 if (slice.isCollective()) { 068 collectiveSliceKeys.put(slice, key); 069 } 070 071 map.put(slicedMapKey, value); 072 slice.afterPut(this, key, value); 073 } 074 075 @Override 076 public void clear() { 077 map.clear(); 078 } 079 080 @Override 081 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) { 082 SlicedMapKey<K, V> slicedMapKey = slice.makeKey(key); 083 //noinspection unchecked 084 V value = (V) map.get(slicedMapKey); 085 return slice.computeValue(this, key, value, value == null && !map.containsKey(slicedMapKey)); 086 } 087 088 @Override 089 @SuppressWarnings("unchecked") 090 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) { 091 assert slice.isCollective() : "Keys are not collected for slice " + slice; 092 return (Collection<K>) collectiveSliceKeys.get(slice); 093 } 094 095 @Override 096 public <K, V> V remove(RemovableSlice<K, V> slice, K key) { 097 //noinspection unchecked 098 return (V) map.remove(slice.makeKey(key)); 099 } 100 101 @NotNull 102 @Override 103 public Iterator<Map.Entry<SlicedMapKey<?, ?>, ?>> iterator() { 104 //noinspection unchecked 105 return (Iterator) map.entrySet().iterator(); 106 } 107 108 @NotNull 109 @Override 110 public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) { 111 ImmutableMap.Builder<K, V> builder = ImmutableMap.builder(); 112 for (Map.Entry<SlicedMapKey<?, ?>, ?> entry : map.entrySet()) { 113 if (entry.getKey().getSlice() == slice) { 114 builder.put((K) entry.getKey().getKey(), (V) entry.getValue()); 115 } 116 } 117 return builder.build(); 118 } 119 }