blob: 41d28da4acb89918a28d58058f981bcfc7d2699f [file] [log] [blame]
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.vcs.persistent;
import com.intellij.openapi.Forceable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataOutputStream;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.UnsyncByteArrayInputStream;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author irengrig
*/
public class SmallMapSerializer<K,V> implements Forceable {
private final Map<KeyWrapper<K>,V> myMap;
private final File myFile;
private final KeyDescriptor<K> myKeyDescriptor;
private final DataExternalizer<V> myValueExternalizer;
private boolean myDirty;
private Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.persistent.SmallMapSerializer");
public SmallMapSerializer(final File file, final KeyDescriptor<K> keyDescriptor, final DataExternalizer<V> valueExternalizer) {
myFile = file;
myKeyDescriptor = keyDescriptor;
myValueExternalizer = valueExternalizer;
myMap = new HashMap<KeyWrapper<K>, V>();
init();
}
private void init() {
try {
final byte[] bytes = FileUtil.loadFileBytes(myFile);
final DataInputStream dis = new DataInputStream(new UnsyncByteArrayInputStream(bytes));
final int size = dis.readInt();
for (int i = 0; i < size; i++) {
final KeyWrapper<K> keyWrapper = new KeyWrapper<K>(myKeyDescriptor, myKeyDescriptor.read(dis));
final V value = myValueExternalizer.read(dis);
myMap.put(keyWrapper, value);
}
} catch (FileNotFoundException ignore) {
} catch (IOException e) {
LOG.error(e);
}
}
public void put(final K key, final V value) {
myMap.put(new KeyWrapper<K>(myKeyDescriptor, key), value);
myDirty = true;
}
public V get(final K key) {
return myMap.get(new KeyWrapper<K>(myKeyDescriptor, key));
}
@Override
public void force() {
if (! myDirty) return;
try{
final BufferExposingByteArrayOutputStream bos = new BufferExposingByteArrayOutputStream();
final DataOutput out = new DataOutputStream(bos);
out.writeInt(myMap.size());
for (Map.Entry<KeyWrapper<K>, V> entry : myMap.entrySet()) {
myKeyDescriptor.save(out, entry.getKey().myKey);
myValueExternalizer.save(out, entry.getValue());
}
FileUtil.writeToFile(myFile, bos.getInternalBuffer(), 0, bos.size());
} catch (IOException e) {
LOG.error(e);
} finally {
myDirty = false;
}
}
@Override
public boolean isDirty() {
return myDirty;
}
private static class KeyWrapper<K> {
private final K myKey;
private final KeyDescriptor<K> myDescriptor;
private KeyWrapper(@NotNull final KeyDescriptor<K> descriptor, final K key) {
myDescriptor = descriptor;
myKey = key;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final KeyWrapper<K> that = (KeyWrapper) o;
return myDescriptor.isEqual(this.myKey, that.myKey);
}
@Override
public int hashCode() {
return myDescriptor.getHashCode(myKey);
}
}
public Collection<K> keySet() {
final ArrayList<K> result = new ArrayList<K>(myMap.size());
for (KeyWrapper<K> keyWrapper : myMap.keySet()) {
result.add(keyWrapper.myKey);
}
return result;
}
}