/*
* This file is part of the HyperGraphDB source distribution. This is copyrighted
* software. For permitted uses, licensing options and redistribution, please see
* the LicensingInformation file at the root level of the distribution.
*
* Copyright (c) 2005-2010 Kobrix Software, Inc. All rights reserved.
*/
package org.hypergraphdb.type;
import java.util.Map;
import java.util.Iterator;
import org.hypergraphdb.HGEMissingData;
import org.hypergraphdb.HGException;
import org.hypergraphdb.HGHandle;
import org.hypergraphdb.HGTypeSystem;
import org.hypergraphdb.HGPersistentHandle;
import org.hypergraphdb.HyperGraph;
import org.hypergraphdb.IncidenceSetRef;
import org.hypergraphdb.LazyRef;
public class MapType implements HGAtomType
{
private HyperGraph hg;
private ObjectFactory<Map<Object, Object>> factory = null;
public MapType(ObjectFactory<Map<Object, Object>> factory)
{
this.factory = factory;
}
public ObjectFactory<?> getFactory()
{
return factory;
}
public void setHyperGraph(HyperGraph hg)
{
this.hg = hg;
}
public Object make(HGPersistentHandle handle, LazyRef<HGHandle[]> targetSet, IncidenceSetRef incidenceSet)
{
Map<Object, Object> result;
if (targetSet == null || targetSet.deref().length == 0)
result = factory.make();
else
result = factory.make(targetSet.deref());
TypeUtils.setValueFor(hg, handle, result);
HGTypeSystem ts = hg.getTypeSystem();
HGPersistentHandle [] layout = hg.getStore().getLink(handle);
if (layout == null)
throw new HGEMissingData(handle);
for (int i = 0; i < layout.length; )
{
Object key, value;
HGPersistentHandle hType = layout[i++];
HGAtomType type = ts.getType(hType);
HGPersistentHandle hValue = layout[i++];
key = TypeUtils.makeValue(hg, hValue, type);
hType = layout[i++];
hValue = layout[i++];
if (hType.equals(hg.getHandleFactory().nullHandle()))
result.put(key, null);
else
{
type = ts.getType(hType);
value = TypeUtils.makeValue(hg, hValue, type);
result.put(key, value);
}
}
return result;
}
@SuppressWarnings("unchecked")
public HGPersistentHandle store(Object instance)
{
HGPersistentHandle result = TypeUtils.getNewHandleFor(hg, instance);
Map map = (Map)instance;
HGPersistentHandle [] layout = new HGPersistentHandle[map.size()*4];
int pos = 0;
for (Iterator i = map.entrySet().iterator(); i.hasNext(); )
{
Map.Entry entry = (Map.Entry)i.next();
Object key = entry.getKey();
Object value = entry.getValue();
HGHandle typeHandle = hg.getTypeSystem().getTypeHandle(key.getClass());
if (typeHandle == null)
throw new HGException("Unable to get HG type for class '" + key.getClass() + "'");
layout[pos++] = hg.getPersistentHandle(typeHandle);
layout[pos++] = TypeUtils.storeValue(hg, key, hg.getTypeSystem().getType(typeHandle));
if (value == null)
{
layout[pos++] = hg.getHandleFactory().nullHandle();
layout[pos++] = hg.getHandleFactory().nullHandle();
}
else
{
typeHandle = hg.getTypeSystem().getTypeHandle(value.getClass());
if (typeHandle == null)
throw new HGException("Unable to get HG type for class '" + value.getClass() + "'");
layout[pos++] = hg.getPersistentHandle(typeHandle);
layout[pos++] = TypeUtils.storeValue(hg, value, hg.getTypeSystem().getType(typeHandle));
}
}
return hg.getStore().store(result, layout);
}
public void release(HGPersistentHandle handle)
{
// TypeUtils.releaseValue(hg, handle);
HGTypeSystem ts = hg.getTypeSystem();
HGPersistentHandle [] layout = hg.getStore().getLink(handle);
for (int i = 0; i < layout.length; )
{
HGPersistentHandle hType = layout[i++];
HGPersistentHandle hValue = layout[i++];
if (!TypeUtils.isValueReleased(hg, hValue))
{
HGAtomType type = ts.getType(hType);
TypeUtils.releaseValue(hg, type, hValue);
//type.release(hValue);
}
hType = layout[i++];
hValue = layout[i++];
if (!hType.equals(hg.getHandleFactory().nullHandle()) &&
!TypeUtils.isValueReleased(hg, hValue))
{
HGAtomType type = ts.getType(hType);
TypeUtils.releaseValue(hg, type, hValue);
//type.release(hValue);
}
}
hg.getStore().removeLink(handle);
}
public boolean subsumes(Object general, Object specific)
{
return false;
}
}