/*******************************************************************************
* Copyright 2015 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.core;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterators;
/**
* Holds edges for a {@link FactorGraph}
* <p>
* @since 0.08
* @author Christopher Barber
*/
class EdgeStateList extends ArrayList<EdgeState>
{
private static final long serialVersionUID = 1L;
/*-------
* State
*/
private final FactorGraph _graph;
private int _nEdges;
// private int _nLocalEdges;
// private int _nOuterEdges;
// private int _nInnerEdges;
/*--------------
* Construction
*/
EdgeStateList(FactorGraph graph)
{
super();
_graph = graph;
}
/*------------------
* Iterable methods
*/
@Override
public Iterator<EdgeState> iterator()
{
// Skip over null entries
return Iterators.filter(super.iterator(), Predicates.notNull());
}
/*--------------
* List methods
*/
@NonNullByDefault(false)
@Override
public boolean add(EdgeState edge)
{
final int index = edge.edgeIndexInParent(_graph);
if (index == size())
{
super.add(edge);
}
else
{
assert(get(index) == null);
super.set(index, edge);
}
updateCounts(edge, 1);
return true;
}
@Override
public EdgeState set(int index, @Nullable EdgeState edge)
{
EdgeState oldEdge = get(index);
if (oldEdge != null)
{
updateCounts(oldEdge, -1);
}
if (edge != null)
{
updateCounts(edge, 1);
}
return super.set(index, edge);
}
/*--------------------------
* Unsupported List methods
*
* These should not be used because they would require edges after the
* removed/inserted ones to be reindexed.
*
* We only implement them to make sure we fail in an obvious way.
*/
@Deprecated
@Override
public void add(int index, @Nullable EdgeState element)
{
throw unsupported();
}
@Deprecated
@Override
public boolean addAll(int index, @Nullable Collection<? extends EdgeState> c)
{
throw unsupported();
}
@Deprecated
@Override
public EdgeState remove(int index)
{
throw unsupported();
}
@Deprecated
@Override
public boolean remove(@Nullable Object o)
{
throw unsupported();
}
@Deprecated
@Override
public boolean removeAll(@Nullable Collection<?> c)
{
throw unsupported();
}
@Override
public boolean retainAll(@Nullable Collection<?> c)
{
throw unsupported();
}
/*-----------------------
* EdgeStateList methods
*/
int allocateIndex()
{
int index = size();
super.add(null);
return index;
}
boolean isInnerEdge(EdgeState edge)
{
return !edge.isLocal() && edge.getFactorParent(_graph) != _graph;
}
boolean isOuterEdge(EdgeState edge)
{
return !edge.isLocal() && edge.getFactorParent(_graph) == _graph;
}
int nEdges()
{
return _nEdges;
}
// int nLocalEdges()
// {
// return _nLocalEdges;
// }
//
// int nOuterEdges()
// {
// return _nOuterEdges;
// }
//
// int nInnerEdges()
// {
// return _nInnerEdges;
// }
private class EdgeStateCollection extends AbstractCollection<EdgeState>
{
private final int _size;
private final Predicate<? super EdgeState> _predicate;
EdgeStateCollection(int size, Predicate<? super EdgeState> predicate)
{
_size = size;
_predicate = predicate;
}
@Override
public Iterator<EdgeState> iterator()
{
return Iterators.filter(EdgeStateList.super.iterator(), _predicate);
}
@Override
public int size()
{
return _size;
}
}
private class EdgeCollection extends AbstractCollection<Edge>
{
private final int _size;
private final Predicate<? super EdgeState> _predicate;
EdgeCollection(int size, Predicate<? super EdgeState> predicate)
{
_size = size;
_predicate = predicate;
}
@Override
public Iterator<Edge> iterator()
{
return new Iterator<Edge> () {
private final Iterator<EdgeState> _iter = Iterators.filter(EdgeStateList.super.iterator(), _predicate);
@Override
public boolean hasNext()
{
return _iter.hasNext();
}
@Override
public Edge next()
{
return new Edge(_graph, _iter.next());
}
@Override
public void remove()
{
throw unsupported();
}
};
}
@Override
public int size()
{
return _size;
}
}
/**
* Returns collection of non-null entries.
* @since 0.08
*/
Collection<EdgeState> allEdgeState()
{
return new EdgeStateCollection(_nEdges, Predicates.notNull());
}
Collection<Edge> allEdges()
{
return new EdgeCollection(_nEdges, Predicates.notNull());
}
/*-----------------
* Private methods
*/
private void updateCounts(EdgeState edge, int increment)
{
_nEdges += increment;
// switch (edge.type(_graph))
// {
// case LOCAL:
// _nLocalEdges += increment;
// break;
// case OUTER:
// _nOuterEdges += increment;
// break;
// case INNER:
// _nInnerEdges += increment;
// break;
// }
}
private UnsupportedOperationException unsupported()
{
return new UnsupportedOperationException();
}
}