/*******************************************************************************
* Copyright (c) 2009-2015 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:
* Jurgen Vinju - initial API and implementation
*******************************************************************************/
package org.rascalmpl.value.impl;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import org.rascalmpl.value.IAnnotatable;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.value.IExternalValue;
import org.rascalmpl.value.IList;
import org.rascalmpl.value.INode;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.IWithKeywordParameters;
import org.rascalmpl.value.exceptions.FactTypeUseException;
import org.rascalmpl.value.type.ExternalType;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.type.TypeFactory;
import org.rascalmpl.value.type.TypeStore;
import org.rascalmpl.value.visitors.IValueVisitor;
import io.usethesource.capsule.AbstractSpecialisedImmutableMap;
import io.usethesource.capsule.ImmutableMap;
/**
* IExternalValue, together with {@link ExternalType} offer a limited form of extensibility
* to the PDB's value and type system. The IExternalValue interface is used to tag extensions,
* such as 'function values' that are not part of the PDB fact exchange and manipulation
* interfaces but do need to integrate with them.
* <br>
* Note that implementations of IExternalValues are obliged to have a type that subclasses
* ExternalType and that they all implement encodeAsConstructor.
* If you do not do this, (de)serialization will not work.
* <br>
* Note that NORMAL USE OF THE PDB DOES NOT REQUIRE IMPLEMENTING THIS INTERFACE
*/
public abstract class AbstractExternalValue implements IExternalValue {
@Override
public boolean isEqual(IValue other) {
return equals(other);
}
public static IConstructor encodeAsConstructor(IExternalValue instance) {
return new IConstructor() {
@Override
public Type getConstructorType() {
return TypeFactory.getInstance().constructor(new TypeStore(), getType(), getName(), new Type[0]);
}
@Override
public Type getType() {
return TypeFactory.getInstance().valueType();
}
@Override
public String getName() {
return instance.getClass().getSimpleName().toLowerCase();
}
@Override
public Type getUninstantiatedConstructorType() {
return getConstructorType();
}
@Override
public IValue get(String label) {
return null;
}
@Override
public IConstructor set(String label, IValue newChild) throws FactTypeUseException {
return this;
}
@Override
public boolean has(String label) {
return false;
}
@Override
public IConstructor set(int index, IValue newChild) {
return this;
}
@Override
public Type getChildrenTypes() {
return TypeFactory.getInstance().voidType();
}
@Override
public boolean declaresAnnotation(TypeStore store, String label) {
return false;
}
@Override
public <T, E extends Throwable> T accept(IValueVisitor<T, E> v)
throws E {
return v.visitConstructor(this);
}
@Override
public boolean isEqual(IValue other) {
return equals(other);
}
@Override
public boolean isAnnotatable() {
return true;
}
@Override
public boolean mayHaveKeywordParameters() {
return true;
}
@Override
public INode replace(int first, int second, int end, IList repl)
throws FactTypeUseException, IndexOutOfBoundsException {
return this;
}
@Override
public int arity() {
return 0;
}
@Override
public IValue get(int i) throws IndexOutOfBoundsException {
return null;
}
@Override
public Iterable<IValue> getChildren() {
return Collections.emptyList();
}
@Override
public Iterator<IValue> iterator() {
return Collections.emptyIterator();
}
@Override
public IAnnotatable<? extends IConstructor> asAnnotatable() {
return new AbstractDefaultAnnotatable<IConstructor>(this) {
@Override
protected IConstructor wrap(IConstructor content,
ImmutableMap<String, IValue> annotations) {
return new AnnotatedConstructorFacade(content, annotations);
}
};
}
@Override
public IWithKeywordParameters<IConstructor> asWithKeywordParameters() {
return new AbstractDefaultWithKeywordParameters<IConstructor>(this, AbstractSpecialisedImmutableMap.<String,IValue>mapOf()) {
@Override
protected IConstructor wrap(IConstructor content, ImmutableMap<String, IValue> parameters) {
return new ConstructorWithKeywordParametersFacade(content, parameters);
}
@Override
public boolean hasParameters() {
return false;
}
@Override
public java.util.Set<String> getParameterNames() {
return Collections.emptySet();
}
@Override
public Map<String, IValue> getParameters() {
return Collections.unmodifiableMap(parameters);
}
};
}
};
}
@Override
public IConstructor encodeAsConstructor() {
return encodeAsConstructor(this);
}
@Override
public boolean isAnnotatable() {
return false;
}
@Override
public IAnnotatable<? extends IValue> asAnnotatable() {
throw new UnsupportedOperationException();
}
@Override
public boolean mayHaveKeywordParameters() {
return false;
}
@Override
public IWithKeywordParameters<? extends IValue> asWithKeywordParameters() {
throw new UnsupportedOperationException();
}
@Override
public <T, E extends Throwable> T accept(IValueVisitor<T, E> v) throws E {
return v.visitExternal(this);
}
}