/*
* Copyright (c) Thomas Parker, 2012.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package pcgen.cdom.facet.base;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import pcgen.base.util.WrappedMapSet;
import pcgen.cdom.base.PCGenIdentifier;
public abstract class AbstractSubAssociationFacet<IDT extends PCGenIdentifier, S1, S2, A>
extends AbstractStorageFacet<IDT>
{
public A get(IDT id, S1 obj1, S2 obj2)
{
if (obj1 == null)
{
throw new IllegalArgumentException(
"Object for getting association may not be null");
}
if (obj2 == null)
{
throw new IllegalArgumentException(
"Object for getting association may not be null");
}
Map<S1, Map<S2, A>> map = getCachedMap(id);
if (map == null)
{
return null;
}
Map<S2, A> subMap = map.get(obj1);
if (subMap == null)
{
return null;
}
return subMap.get(obj2);
}
public boolean set(IDT id, S1 obj1, S2 obj2, A association)
{
if (obj1 == null)
{
throw new IllegalArgumentException("Object to add may not be null");
}
if (obj2 == null)
{
throw new IllegalArgumentException("Object to add may not be null");
}
if (association == null)
{
throw new IllegalArgumentException("Association may not be null");
}
Map<S2, A> map = getConstructingCachedMap(id, obj1);
A old = map.put(obj2, association);
return old == null;
}
public void remove(IDT id, S1 obj1, S2 obj2)
{
Map<S1, Map<S2, A>> map = getCachedMap(id);
if (map != null)
{
Map<S2, A> subMap = map.get(obj1);
if (subMap != null)
{
map.remove(obj2);
if (subMap.isEmpty())
{
map.remove(obj1);
}
}
}
}
public Map<S1, Map<S2, A>> removeAll(IDT id)
{
Map<S1, Map<S2, A>> componentMap =
(Map<S1, Map<S2, A>>) removeCache(id);
if (componentMap == null)
{
return Collections.emptyMap();
}
return componentMap;
}
public boolean isEmpty(IDT id)
{
Map<S1, Map<S2, A>> map = getCachedMap(id);
return map == null || map.isEmpty();
}
protected Map<S1, Map<S2, A>> getCachedMap(IDT id)
{
return (Map<S1, Map<S2, A>>) getCache(id);
}
private Map<S2, A> getConstructingCachedMap(IDT id, S1 obj1)
{
Map<S1, Map<S2, A>> map = getCachedMap(id);
if (map == null)
{
map = getComponentMap();
setCache(id, map);
}
Map<S2, A> subMap = map.get(obj1);
if (subMap == null)
{
subMap = getSubComponentMap();
map.put(obj1, subMap);
}
return subMap;
}
protected Map<S1, Map<S2, A>> getComponentMap()
{
return new IdentityHashMap<>();
}
protected Map<S2, A> getSubComponentMap()
{
return new IdentityHashMap<>();
}
@Override
public void copyContents(IDT source, IDT destination)
{
Map<S1, Map<S2, A>> sourceMap = getCachedMap(source);
if (sourceMap != null)
{
for (Map.Entry<S1, Map<S2, A>> me : sourceMap.entrySet())
{
getConstructingCachedMap(destination, me.getKey()).putAll(
me.getValue());
}
}
}
public Collection<S1> getObjects(IDT id)
{
Map<S1, Map<S2, A>> map = getCachedMap(id);
if (map == null)
{
return Collections.emptyList();
}
WrappedMapSet<S1> set =
new WrappedMapSet<>(getComponentMap().getClass());
set.addAll(map.keySet());
return set;
}
public Collection<S2> getSubObjects(IDT id, S1 obj1)
{
Map<S1, Map<S2, A>> map = getCachedMap(id);
if (map == null)
{
return Collections.emptyList();
}
Map<S2, A> subMap = map.get(obj1);
if (subMap == null)
{
return Collections.emptyList();
}
WrappedMapSet<S2> set =
new WrappedMapSet<>(getSubComponentMap().getClass());
set.addAll(subMap.keySet());
return set;
}
}