/*******************************************************************************
* Copyright (c) 2007, 2008, 2012 IBM Corporation & CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation
* Jurgen Vinju (jurgen@vinju.org)
* Anya Helene Bagge - rational support, labeled maps and tuples
*******************************************************************************/
package org.rascalmpl.value.impl.reference;
import java.util.Objects;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.value.IList;
import org.rascalmpl.value.IListWriter;
import org.rascalmpl.value.IMap;
import org.rascalmpl.value.IMapWriter;
import org.rascalmpl.value.INode;
import org.rascalmpl.value.ISet;
import org.rascalmpl.value.ISetWriter;
import org.rascalmpl.value.ITuple;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.exceptions.FactTypeUseException;
import org.rascalmpl.value.exceptions.UnexpectedElementTypeException;
import org.rascalmpl.value.impl.primitive.AbstractPrimitiveValueFactory;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.type.TypeFactory;
/**
* This is a reference implementation for an @{link IValueFactory}. It uses
* the Java standard library to implement it in a most straightforward but
* not necessarily very efficient manner.
*/
public class ValueFactory extends AbstractPrimitiveValueFactory {
private static final ValueFactory sInstance = new ValueFactory();
public static ValueFactory getInstance() {
return sInstance;
}
protected ValueFactory() {
super();
}
protected static void checkNull(Object... args) {
for (Object a : args) {
Objects.requireNonNull(a);
}
}
protected static void checkNull(java.util.Map<Object, Object> args) {
for (java.util.Map.Entry<Object, Object> entry : args.entrySet()) {
if (entry == null || entry.getKey() == null || entry.getValue() == null) {
throw new NullPointerException();
}
}
}
@Override
public ISet relation(Type tupleType) {
checkNull(tupleType);
return relationWriter(tupleType).done();
}
@Override
public ISet relation(IValue... tuples) {
checkNull((Object[]) tuples);
Type elementType = lub(tuples);
if (!elementType.isFixedWidth()) {
TypeFactory tf = TypeFactory.getInstance();
throw new UnexpectedElementTypeException(tf.tupleType(tf.voidType()), elementType);
}
ISetWriter rw = setWriter(elementType);
rw.insert(tuples);
return rw.done();
}
@Override
public ISetWriter relationWriter(Type tupleType) {
checkNull(tupleType);
return new SetWriter(tupleType);
}
@Override
public ISetWriter relationWriter() {
return new SetWriter();
}
@Override
public ISet set(Type eltType){
checkNull(eltType);
return setWriter(eltType).done();
}
@Override
public ISetWriter setWriter(Type eltType) {
checkNull(eltType);
return new SetWriter(eltType);
}
@Override
public ISetWriter setWriter() {
return new SetWriter();
}
@Override
public ISet set(IValue... elems) throws FactTypeUseException {
checkNull((Object[]) elems);
Type elementType = lub(elems);
ISetWriter sw = setWriter(elementType);
sw.insert(elems);
return sw.done();
}
@Override
public IList list(Type eltType) {
checkNull(eltType);
return listWriter(eltType).done();
}
@Override
public IListWriter listWriter(Type eltType) {
checkNull(eltType);
return new ListWriter(eltType);
}
@Override
public IListWriter listWriter() {
return new ListWriter();
}
@Override
public IList list(IValue... rest) {
checkNull((Object[]) rest);
Type eltType = lub(rest);
IListWriter lw = listWriter(eltType);
lw.append(rest);
return lw.done();
}
private Type lub(IValue... elems) {
checkNull((Object[]) elems);
Type elementType = TypeFactory.getInstance().voidType();
for (IValue elem : elems) {
elementType = elementType.lub(elem.getType());
}
return elementType;
}
@Override
public ITuple tuple() {
return new Tuple(new IValue[0]);
}
@Override
public ITuple tuple(IValue... args) {
checkNull((Object[]) args);
return new Tuple(args.clone());
}
@Override
public ITuple tuple(Type type, IValue... args) {
checkNull((Object[]) args);
return new Tuple(type, args.clone());
}
@Override
public INode node(String name) {
checkNull(name);
return new Node(name);
}
@Override
public INode node(String name, java.util.Map<String, IValue> annotations, IValue... children) {
checkNull(name);
checkNull(annotations);
checkNull((Object[]) children);
return new Node(name, children).asAnnotatable().setAnnotations(annotations);
}
@Override
public INode node(String name, IValue... children) {
checkNull(name);
checkNull((Object[]) children);
return new Node(name, children);
}
@Override
public INode node(String name, IValue[] children, java.util.Map<String, IValue> keyArgValues)
throws FactTypeUseException {
checkNull(name);
checkNull((Object[]) children);
// checkNull(keyArgValues); // fails; are null values allowed?
return new Node(name, children.clone(), keyArgValues);
}
@Override
public IConstructor constructor(Type constructorType, IValue... children) {
checkNull(constructorType);
checkNull((Object[]) children);
Type instantiatedType = inferInstantiatedTypeOfConstructor(constructorType, children);
return new Constructor(instantiatedType, children);
}
@Override
public IConstructor constructor(Type constructorType, java.util.Map<String,IValue> annotations, IValue... children) {
checkNull(constructorType);
checkNull(annotations);
checkNull((Object[]) children);
return new Constructor(constructorType, children).asAnnotatable().setAnnotations(annotations);
}
@Override
public IConstructor constructor(Type constructorType, IValue[] children, java.util.Map<String,IValue> kwParams) {
checkNull(constructorType);
checkNull(kwParams);
checkNull((Object[]) children);
return new Constructor(constructorType, children, kwParams);
}
@Override
public IConstructor constructor(Type constructorType) {
checkNull(constructorType);
Type instantiatedType = inferInstantiatedTypeOfConstructor(constructorType, new IValue[0]);
return new Constructor(instantiatedType);
}
@Override
public IMap map(Type keyType, Type valueType) {
checkNull(keyType);
checkNull(valueType);
return mapWriter(keyType, valueType).done();
}
@Override
public IMap map(Type mapType) {
checkNull(mapType);
return mapWriter(mapType).done();
}
@Override
public IMapWriter mapWriter(Type keyType, Type valueType) {
checkNull(keyType);
checkNull(valueType);
return new MapWriter(TypeFactory.getInstance().mapType(keyType, valueType));
}
@Override
public IMapWriter mapWriter(Type mapType) {
checkNull(mapType);
return new MapWriter(mapType);
}
@Override
public IMapWriter mapWriter() {
return new MapWriter();
}
@Override
public IListWriter listRelationWriter(Type tupleType) {
checkNull(tupleType);
return new ListWriter(tupleType);
}
@Override
public IListWriter listRelationWriter() {
return new ListWriter();
}
@Override
public IList listRelation(Type tupleType) {
checkNull(tupleType);
return listWriter(tupleType).done();
}
@Override
public IList listRelation(IValue... tuples) {
checkNull((Object[]) tuples);
Type elementType = lub(tuples);
if (!elementType.isFixedWidth()) {
TypeFactory tf = TypeFactory.getInstance();
throw new UnexpectedElementTypeException(tf.tupleType(tf.voidType()), elementType);
}
IListWriter rw = listRelationWriter(elementType);
rw.append(tuples);
return rw.done();
}
@Override
public String toString() {
return "VF_PDB_REFERENCE";
}
}