io.janusproject.kernel.services.hazelcast.HazelcastDMultiMapView.java Source code

Java tutorial

Introduction

Here is the source code for io.janusproject.kernel.services.hazelcast.HazelcastDMultiMapView.java

Source

/*
 * $Id$
 *
 * Janus platform is an open-source multiagent platform.
 * More details on http://www.janusproject.io
 *
 * Copyright (C) 2014 Sebastian RODRIGUEZ, Nicolas GAUD, Stphane GALLAND.
 *
 * 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 io.janusproject.kernel.services.hazelcast;

import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.SetMultimap;
import com.hazelcast.core.MultiMap;

import java.io.Serializable;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import io.janusproject.util.AbstractDMultiMapView;
import io.janusproject.util.DataViewDelegate;
import io.janusproject.util.DataViewDelegate.Delegator;
import io.janusproject.util.MultisetView;

/**
 * A view from the Hazelcast multimap to DMultiMap.
 *
 * @param <K> - type of the keys.
 * @param <V> - type of the values.
 * @author $Author: sgalland$
 * @version $FullVersion$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 */
public class HazelcastDMultiMapView<K, V> extends AbstractDMultiMapView<K, V> implements SetMultimap<K, V> {

    private static final long serialVersionUID = -6970650402150118406L;

    private final Multimap<K, V> map;

    /**
     * @param map - the multimap.
     */
    public HazelcastDMultiMapView(MultiMap<K, V> map) {
        super(map.getName());
        this.map = new Wrapper<>(map);
    }

    @Override
    public boolean isBackedCollection() {
        return false;
    }

    @Override
    public Multimap<K, V> getDelegatedObject() {
        return this.map;
    }

    @Override
    public boolean equals(Object obj) {
        return getDelegatedObject().equals(DataViewDelegate.undelegate(obj));
    }

    @Override
    public int hashCode() {
        return getDelegatedObject().hashCode();
    }

    @Override
    public String toString() {
        return getDelegatedObject().toString();
    }

    @Override
    public synchronized Set<V> removeAll(Object key) {
        return (Set<V>) super.removeAll(key);
    }

    @Override
    public Set<V> replaceValues(K key, Iterable<? extends V> values) {
        return (Set<V>) super.replaceValues(key, values);
    }

    @Override
    public Set<V> get(K key) {
        return (Set<V>) super.get(key);
    }

    @Override
    public Set<Entry<K, V>> entries() {
        return new EntryCollectionView(getDelegatedObject().entries());

    }

    /**
     * @param <K>
     * @param <V>
     * @author $Author: sgalland$
     * @version $FullVersion$
     * @mavengroupid $GroupId$
     * @mavenartifactid $ArtifactId$
     */
    private static class Wrapper<K, V> implements Multimap<K, V> {

        private final MultiMap<K, V> map;
        private Map<K, Collection<V>> mapView;

        public Wrapper(MultiMap<K, V> map) {
            this.map = map;
        }

        @Override
        public boolean equals(Object obj) {
            return this.map.equals(obj);
        }

        @Override
        public int hashCode() {
            return this.map.hashCode();
        }

        @Override
        public String toString() {
            return this.map.toString();
        }

        @Override
        public int size() {
            return this.map.size();
        }

        @Override
        public boolean isEmpty() {
            return this.map.size() == 0;
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean containsKey(Object key) {
            try {
                return this.map.containsKey((K) key);
            } catch (ClassCastException _) {
                return false;
            }
        }

        @Override
        public boolean containsValue(Object value) {
            return this.map.containsValue(value);
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean containsEntry(Object key, Object value) {
            try {
                return this.map.containsEntry((K) key, (V) value);
            } catch (ClassCastException _) {
                return false;
            }
        }

        @Override
        public Collection<V> get(K key) {
            return this.map.get(key);
        }

        @Override
        public boolean put(K key, V value) {
            if (this.map.put(key, value)) {
                this.mapView = null;
                return true;
            }
            return false;
        }

        @Override
        public boolean putAll(K key, Iterable<? extends V> values) {
            boolean changed = false;
            for (V value : values) {
                if (this.map.put(key, value)) {
                    changed = true;
                }
            }
            if (changed) {
                this.mapView = null;
            }
            return changed;
        }

        @Override
        public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
            boolean changed = false;
            for (Entry<? extends K, ? extends V> entry : multimap.entries()) {
                if (this.map.put(entry.getKey(), entry.getValue())) {
                    changed = true;
                }
            }
            if (changed) {
                this.mapView = null;
            }
            return changed;
        }

        @Override
        public boolean remove(Object key, Object value) {
            if (this.map.remove(key, value)) {
                this.mapView = null;
                return true;
            }
            return false;
        }

        @Override
        public Collection<V> removeAll(Object key) {
            this.mapView = null;
            return this.map.remove(key);
        }

        @Override
        public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
            this.mapView = null;
            Collection<V> oldValue = this.map.remove(key);
            for (V value : values) {
                this.map.put(key, value);
            }
            return oldValue;
        }

        @Override
        public void clear() {
            this.map.clear();
        }

        @Override
        public Set<K> keySet() {
            return this.map.keySet();
        }

        @Override
        public Collection<V> values() {
            return this.map.values();
        }

        @Override
        public Collection<Entry<K, V>> entries() {
            return this.map.entrySet();
        }

        @Override
        public Multiset<K> keys() {
            return new MultisetView<>(this);
        }

        @Override
        public Map<K, Collection<V>> asMap() {
            if (this.mapView == null) {
                this.mapView = createMapView();
            }
            return this.mapView;
        }

        private Map<K, Collection<V>> createMapView() {
            Map<K, Collection<V>> map = Maps.newHashMap();
            K oldKey = null;
            Collection<V> oldValues = null;
            for (Entry<K, V> entry : this.map.entrySet()) {
                Collection<V> values;
                if (Objects.equal(entry.getKey(), oldKey)) {
                    values = oldValues;
                } else {
                    values = map.get(entry.getKey());
                }
                if (values == null) {
                    values = Lists.newArrayList();
                    map.put(entry.getKey(), values);
                }
                values.add(entry.getValue());
                oldKey = entry.getKey();
                oldValues = values;
            }
            return map;
        }

    }

    /**
     * A view on the entries in a {@link AbstractDMultiMapView}.
     *
     * @author $Author: sgalland$
     * @version $FullVersion$
     * @mavengroupid $GroupId$
     * @mavenartifactid $ArtifactId$
     */
    protected class EntryCollectionView extends AbstractSet<Entry<K, V>>
            implements Serializable, Delegator<Collection<Entry<K, V>>> {

        private static final long serialVersionUID = 3746778947439539504L;

        private final Collection<Entry<K, V>> entries;

        /**
         * @param entries - the entries in the multimap.
         */
        public EntryCollectionView(Collection<Entry<K, V>> entries) {
            this.entries = entries;
        }

        @Override
        public Set<Entry<K, V>> getDelegatedObject() {
            return (Set<Entry<K, V>>) HazelcastDMultiMapView.this.getDelegatedObject().entries();
        }

        @Override
        public boolean equals(Object obj) {
            return getDelegatedObject().equals(DataViewDelegate.undelegate(obj));
        }

        @Override
        public int hashCode() {
            return getDelegatedObject().hashCode();
        }

        @Override
        public String toString() {
            return getDelegatedObject().toString();
        }

        @Override
        public int size() {
            return this.entries.size();
        }

        @Override
        public Iterator<Entry<K, V>> iterator() {
            return new EntryIterator(this.entries.iterator());
        }

        @SuppressWarnings("synthetic-access")
        @Override
        public boolean add(Entry<K, V> e) {
            if (this.entries.add(e)) {
                fireEntryAdded(e.getKey(), e.getValue());
                return true;
            }
            return false;
        }

        /**
         * @author $Author: sgalland$
         * @version $FullVersion$
         * @mavengroupid $GroupId$
         * @mavenartifactid $ArtifactId$
         */
        private class EntryIterator implements Iterator<Entry<K, V>> {

            private final Iterator<Entry<K, V>> iterator;
            private Entry<K, V> entry;

            public EntryIterator(Iterator<Entry<K, V>> iterator) {
                this.iterator = iterator;
            }

            @Override
            public boolean hasNext() {
                return this.iterator.hasNext();
            }

            @Override
            public Entry<K, V> next() {
                this.entry = this.iterator.next();
                return this.entry;
            }

            @SuppressWarnings("synthetic-access")
            @Override
            public void remove() {
                this.iterator.remove();
                fireEntryRemoved(this.entry.getKey(), this.entry.getValue());
            }
        }

    }

}