/*******************************************************************************
* Copyright (c) 2013-2014 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:
*
* * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI
*******************************************************************************/
package org.rascalmpl.value.impl.persistent;
import java.util.Comparator;
import org.rascalmpl.value.ISet;
import org.rascalmpl.value.ISetWriter;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.exceptions.FactTypeUseException;
import org.rascalmpl.value.exceptions.UnexpectedElementTypeException;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.util.AbstractTypeBag;
import org.rascalmpl.value.util.EqualityUtils;
import io.usethesource.capsule.DefaultTrieSet;
import io.usethesource.capsule.TransientSet;
class SetWriter implements ISetWriter {
@SuppressWarnings("unchecked")
private static final Comparator<Object> equivalenceComparator = EqualityUtils
.getEquivalenceComparator();
protected AbstractTypeBag elementTypeBag;
protected final TransientSet<IValue> setContent;
protected final boolean checkUpperBound;
protected final Type upperBoundType;
protected ISet constructedSet;
SetWriter(Type upperBoundType) {
super();
this.checkUpperBound = true;
this.upperBoundType = upperBoundType;
elementTypeBag = AbstractTypeBag.of();
setContent = DefaultTrieSet.transientOf();
constructedSet = null;
}
SetWriter() {
super();
this.checkUpperBound = false;
this.upperBoundType = null;
elementTypeBag = AbstractTypeBag.of();
setContent = DefaultTrieSet.transientOf();
constructedSet = null;
}
private void put(IValue element) {
final Type elementType = element.getType();
if (checkUpperBound && !elementType.isSubtypeOf(upperBoundType)) {
throw new UnexpectedElementTypeException(upperBoundType, elementType);
}
boolean result = setContent.__insertEquivalent(element, equivalenceComparator);
if (result) {
elementTypeBag = elementTypeBag.increase(elementType);
}
}
@Override
public void insert(IValue... values) throws FactTypeUseException {
checkMutation();
for (IValue item : values) {
put(item);
}
}
@Override
public void insertAll(Iterable<? extends IValue> collection) throws FactTypeUseException {
checkMutation();
for (IValue item : collection) {
put(item);
}
}
@Override
public ISet done() {
if (constructedSet == null) {
constructedSet = new PDBPersistentHashSet(elementTypeBag, setContent.freeze());
}
return constructedSet;
}
private void checkMutation() {
if (constructedSet != null) {
throw new UnsupportedOperationException("Mutation of a finalized set is not supported.");
}
}
@Override
public String toString() {
return setContent.toString();
}
}