/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.db.impl.query; import java.util.concurrent.atomic.AtomicInteger; import org.simantics.db.common.exception.DebugException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.impl.procedure.IntProcedureAdapter; import org.simantics.db.impl.procedure.InternalProcedure; import org.simantics.db.procedure.ListenerBase; final public class OrderedSet extends CollectionUnaryQuery { public OrderedSet(final int r) { super(r); } @Override final public void removeEntry(QueryProcessor provider) { provider.cache.remove(this); } private static int nextElement(ReadGraphImpl graph, int current, int orderedSet, OrderedSet entry, final IntProcedure procedure) throws DatabaseException { QueryProcessor processor = graph.processor; processor.querySupport.ensureLoaded(graph, current); AtomicInteger res = new AtomicInteger(0); boolean found = processor.querySupport.getObjects(graph, current, orderedSet, new IntProcedure() { @Override public void execute(ReadGraphImpl graph, int i) throws DatabaseException { if(i != orderedSet) { if(entry != null) entry.addOrSet(i); procedure.execute(graph, i); } res.set(i); } @Override public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException { if(DebugException.DEBUG) new DebugException(t).printStackTrace(); procedure.exception(graph, t); } @Override public void finished(ReadGraphImpl graph) { } }); if(res.get() == orderedSet) { if(entry != null) entry.finish(graph, processor); procedure.finished(graph); } return res.get(); } @Override public void clearResult(QuerySupport support) { setResult(new IntArray()); } //@Override public Object compute(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException { computeForEach(graph, id, this, procedure); return getResult(); } static void computeForEach(ReadGraphImpl graph, int orderedSet, final OrderedSet entry, final IntProcedure procedure) throws DatabaseException { int current = nextElement(graph, orderedSet, orderedSet, entry, procedure); while(current != orderedSet) { current = nextElement(graph, current, orderedSet, entry, procedure); } } @Override public String toString() { return "OrderedSet[" + id + "]"; } final private void finish(ReadGraphImpl graph, QueryProcessor provider) { assert(isPending()); synchronized(this) { setReady(); } } final public void addOrSet(int add) { assert(isPending()); IntArray value = (IntArray)getResult(); value.add(add); } @Override public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException { assert(isReady()); if(handleException(graph, procedure)) return EXCEPTED; final IntArray value = (IntArray)getResult(); if(value.data == null) { if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData); } else { for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]); } procedure.finished(graph); return value; } @Override public void recompute(ReadGraphImpl graph) throws DatabaseException { compute(graph, new IntProcedureAdapter() { @Override public void finished(ReadGraphImpl graph) { } @Override public void exception(ReadGraphImpl graph, Throwable t) { throw new Error("Error in recompute.", t); } }); } }