/******************************************************************************* * Copyright 2012 Analog Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ package com.analog.lyric.dimple.model.repeated; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Objects; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import com.analog.lyric.dimple.exceptions.DimpleException; import com.analog.lyric.dimple.model.domains.Domain; import com.analog.lyric.dimple.model.variables.Variable; import com.analog.lyric.dimple.solvers.interfaces.ISolverVariable; public abstract class VariableStreamBase<V extends Variable> implements IVariableStreamSlice<V> { private Domain _domain; private ArrayList<V> _variables = new ArrayList<>(); private @Nullable IDataSource _dataSource = null; private @Nullable IDataSink _dataSink = null; private ArrayList<VariableStreamSlice<V>> _slices = new ArrayList<>(); private VariableStreamSlice<V> _slice; private final @Nullable String _namePrefix; protected VariableStreamBase(Domain domain, @Nullable String namePrefix) { _domain = domain; _slice = getSlice(0); _namePrefix = namePrefix; } /** * Return {@link Class} of variable used by this stream. * @since 0.08 */ protected abstract Class<? extends V> variableType(); public int size() { return _variables.size(); } @SuppressWarnings("unchecked") public V [] getVariables() { return _variables.toArray((V[])Array.newInstance(variableType(), _variables.size())); } public boolean contains(Variable vb) { return _variables.contains(vb); } @SuppressWarnings("deprecation") public void advanceState() { final IDataSink dataSink = _dataSink; if (dataSink != null) { Object output = _variables.get(0).getBeliefObject(); dataSink.push(Objects.requireNonNull(output)); } for (int i = 0; i < _variables.size()-1; i++) { Variable var = _variables.get(i), ovar = _variables.get(i+1); var.moveInputs(ovar); final ISolverVariable svar = var.requireSolver("advanceState"), osvar = ovar.requireSolver("advanceState"); svar.moveNonEdgeSpecificState(osvar); } Variable lastVar = _variables.get(_variables.size()-1); lastVar.requireSolver("advanceState").createNonEdgeSpecificState(); final IDataSource dataSource = _dataSource; if (dataSource != null) { Object input = dataSource.getNext(); lastVar.setInputObject(input); lastVar.requireSolver("advanceState").updatePriorAndCondition(); } else { lastVar.setPrior(null); } } public VariableStreamSlice<V> getSlice(int start) { VariableStreamSlice<V> ss = new VariableStreamSlice<>(start,this); _slices.add(ss); return ss; } public @Nullable IDataSink getDataSink() { return _dataSink; } public @Nullable IDataSource getDataSource() { return _dataSource; } public void setDataSink(IDataSink sink) { _dataSink = sink; } @SuppressWarnings("deprecation") public void setDataSource(IDataSource source) { _dataSource = source; //fill variables with data for (Variable vb : _variables) { if (!source.hasNext()) throw new DimpleException("not enough data in data source"); vb.setInputObject(source.getNext()); } } /** * The variable domain of the stream. * @since 0.07 */ public Domain getDomain() { return _domain; } abstract protected V instantiateVariable(Domain domain) ; @SuppressWarnings("deprecation") protected V createVariable(int index) { V tmp; tmp = instantiateVariable(_domain); if (_namePrefix != null) { tmp.setName(_namePrefix + index); } final IDataSource dataSource = _dataSource; if (dataSource != null) { if (!dataSource.hasNext()) throw new DimpleException("out of data"); tmp.setInputObject(dataSource.getNext()); } return tmp; } public boolean variableAvailableFor(double index) { if (index < 0) { return false; } for (int i = _variables.size(); i <= index; ++i) { if (!hasNext()) { return false; } _variables.add(createVariable(i)); } return index < _variables.size(); } @NonNull // FIXME - workaround for Eclipse JDT bug (467610?) @Override public V get(int index) { return get(index,false); } @NonNull // FIXME - workaround for Eclipse JDT bug (467610?) @Override public V get(int index,boolean createIfDoesntExist) { if (index < 0) throw new DimpleException("negative indexing not allowed"); if (!createIfDoesntExist && index >= _variables.size()) throw new DimpleException("A variable has not yet been instantiated for the specified index: " + index); for (int i = _variables.size(); i <= index; ++i) { _variables.add(createVariable(i)); } return _variables.get(index); } public boolean hasNext() { final IDataSource dataSource = _dataSource; if (dataSource == null) return true; else return dataSource.hasNext(); } public IVariableStreamSlice<V> copy() { return _slice.copy(); } @Override public VariableStreamBase<V> getStream() { return this; } int indexOf(Variable vb) { return _variables.indexOf(vb); } void cleanupUnusedVariables() { for(int i = _variables.size()-1; i >= 0; i--) { if (_variables.get(i).getParentGraph()==null) _variables.remove(i); } } }