/*******************************************************************************
* Copyright (c) 2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse public static License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
* * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
* * Paul Klint - Paul.Klint@cwi.nl - CWI
* * Anya Helene Bagge - anya@ii.uib.no - UiB
*
* Based on code by:
*
* * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation
*******************************************************************************/
package org.rascalmpl.value.impl.func;
import java.util.Iterator;
import java.util.Map.Entry;
import org.rascalmpl.value.IMap;
import org.rascalmpl.value.IMapWriter;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.IValueFactory;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.type.TypeFactory;
public final class MapFunctions {
@SuppressWarnings("unused")
private final static TypeFactory TF = TypeFactory.getInstance();
public static IMap compose(IValueFactory vf, IMap map1, IMap map2) {
Type newMapType;
if (map1.getType().hasFieldNames() && map2.getType().hasFieldNames()) {
newMapType = TypeFactory.getInstance().mapType(
map1.getType().getKeyType(), map1.getType().getKeyLabel(),
map2.getType().getValueType(),
map2.getType().getValueLabel());
} else {
newMapType = TypeFactory.getInstance().mapType(map1.getKeyType(),
map2.getValueType());
}
IMapWriter w = vf.mapWriter(newMapType);
Iterator<Entry<IValue, IValue>> iter = map1.entryIterator();
while (iter.hasNext()) {
Entry<IValue, IValue> e = iter.next();
IValue value = map2.get(e.getValue());
if (value != null) {
w.put(e.getKey(), value);
}
}
return w.done();
}
public static IMap put(IValueFactory vf, IMap map1, IValue key, IValue value) {
IMapWriter sw = vf.mapWriter(map1.getType());
sw.putAll(map1);
sw.put(key, value);
return sw.done();
}
public static IMap join(IValueFactory vf, IMap map1, IMap map2) {
IMapWriter sw = vf.mapWriter(map1.getType().lub(map2.getType()));
sw.putAll(map1);
sw.putAll(map2);
return sw.done();
}
public static IMap common(IValueFactory vf, IMap map1, IMap map2) {
IMapWriter sw = vf.mapWriter(map1.getType().lub(map2.getType()));
for (IValue key : map1) {
IValue thisValue = map1.get(key);
IValue otherValue = map2.get(key);
if (otherValue != null && thisValue.isEqual(otherValue)) {
sw.put(key, thisValue);
}
}
return sw.done();
}
public static IMap remove(IValueFactory vf, IMap map1, IMap map2) {
IMapWriter sw = vf.mapWriter(map1.getType());
for (IValue key : map1) {
if (!map2.containsKey(key)) {
sw.put(key, map1.get(key));
}
}
return sw.done();
}
public static boolean isSubMap(IValueFactory vf, IMap map1, IMap map2) {
for (IValue key : map1) {
if (!map2.containsKey(key)) {
return false;
}
if (!map2.get(key).isEqual(map1.get(key))) {
return false;
}
}
return true;
}
public static int hashCode(IValueFactory vf, IMap map1) {
int hash = 0;
Iterator<IValue> keyIterator = map1.iterator();
while (keyIterator.hasNext()) {
IValue key = keyIterator.next();
hash ^= key.hashCode();
}
return hash;
}
public static boolean equals(IValueFactory vf, IMap map1, Object other){
if (other == map1) return true;
if (other == null) return false;
if (other instanceof IMap) {
IMap map2 = (IMap) other;
if (map1.getType() != map2.getType()) return false;
if (hashCode(vf, map1) != hashCode(vf, map2)) return false;
if (map1.size() == map2.size()) {
for (IValue k1 : map1) {
if (containsKeyWithEquals(vf, map2, k1) == false) { // call to Object.equals(Object)
return false;
} else if (map2.get(k1).equals(map1.get(k1)) == false) { // call to Object.equals(Object)
return false;
}
}
return true;
}
}
return false;
}
public static boolean isEqual(IValueFactory vf, IMap map1, IValue other){
if (other == map1) return true;
if (other == null) return false;
if (other instanceof IMap) {
IMap map2 = (IMap) other;
if (map1.size() == map2.size()) {
for (IValue k1 : map1) {
if (containsKey(vf, map2, k1) == false) { // call to IValue.isEqual(IValue)
return false;
} else if (map2.get(k1).isEqual(map1.get(k1)) == false) { // call to IValue.isEqual(IValue)
return false;
}
}
return true;
}
}
return false;
}
public static IValue get(IValueFactory valueFactory, IMap map1, IValue key) {
for (Iterator<Entry<IValue, IValue>> iterator = map1.entryIterator(); iterator.hasNext();) {
Entry<IValue, IValue> entry = iterator.next();
if (entry.getKey().isEqual(key)) {
return entry.getValue();
}
}
return null;
}
public static boolean containsKeyWithEquals(IValueFactory valueFactory, IMap map1, IValue key) {
for (Iterator<IValue> iterator = map1.iterator(); iterator.hasNext();) {
if (iterator.next().equals(key)) {
return true;
}
}
return false;
}
public static boolean containsKey(IValueFactory valueFactory, IMap map1, IValue key) {
for (Iterator<IValue> iterator = map1.iterator(); iterator.hasNext();) {
if (iterator.next().isEqual(key)) {
return true;
}
}
return false;
}
public static boolean containsValueWithEquals(IValueFactory valueFactory, IMap map1,
IValue value) {
for (Iterator<IValue> iterator = map1.valueIterator(); iterator.hasNext();) {
if (iterator.next().equals(value)) {
return true;
}
}
return false;
}
public static boolean containsValue(IValueFactory valueFactory, IMap map1, IValue value) {
for (Iterator<IValue> iterator = map1.valueIterator(); iterator.hasNext();) {
if (iterator.next().isEqual(value)) {
return true;
}
}
return false;
}
}