) extendedDataType;
return edt.getOutputValue((O) extendedData.get(edt), i);
}
/**
* Defines the compression method for stored data.
*
* Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
*
* BSD-style license. See OpenTrafficSim License.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mei 2017
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
public enum CompressionMethod
{
/** No compression. */
NONE,
/** Duplicate info per trajectory is only stored at the first sample, and empty for other samples. */
OMIT_DUPLICATE_INFO,
/** Zip compression. */
ZIP,
}
/**
* Loads sampler data from a file. There are a few limitations with respect to live sampled data:
*
* - The number of decimals in numeric data is equal to the stored format.
* - All extended data types are stored as {@code String}.
* - Meta data types are not recognized, and hence stored as extended data types. Values are always stored as
* {@code String}.
*
* @param file String; file
* @return Sampler data from file
*/
public static SamplerData> loadFromFile(final String file)
{
return loadFromFile(file, new LinkedHashSet>(), new LinkedHashSet>());
}
/**
* Loads sampler data from a file. There are a few limitations with respect to live sampled data:
*
* - The number of decimals in numeric data is equal to the stored format.
* - All extended data types are stored as {@code String}, unless recognized by id as provided.
* - Meta data types are not recognized, and hence stored as extended data types, unless recognized by id as provided.
* Values are always stored as {@code String}.
*
* @param file String; file
* @param extendedDataTypes Set<ExtendedDataType<?, ?, ?, ?>>; extended data types
* @param metaDataTypes Set<MetaDataType<?>>; meta data types
* @return Sampler data from file
*/
@SuppressWarnings("unchecked")
public static SamplerData> loadFromFile(final String file, final Set> extendedDataTypes,
final Set> metaDataTypes)
{
/*
@SuppressWarnings("rawtypes")
SamplerData samplerData = new SamplerData();
// "traj#,linkId,laneId&dir,gtuId,t,x,v,a" meta data types, extended data types
// we can use the default meta data types: cross section, destination, origin, route and GTU type
Getter nodes = new Getter((id) -> new NodeData(id));
Getter gtuTypes = new Getter((id) -> new GtuTypeData(id));
Getter routes = new Getter((id) -> new RouteData(id));
Getter links = new Getter((id) -> new LinkData(id));
BiGetter lanes = new BiGetter((id, link) -> new LaneData(id, link));
BiGetter laneDirections = new BiGetter((dir,
lane) -> new KpiLaneDirection(lane, dir.equals("+") ? KpiGtuDirectionality.DIR_PLUS
: KpiGtuDirectionality.DIR_MINUS));
@SuppressWarnings("rawtypes")
Function groupFunction = (laneDir) -> new TrajectoryGroup(Time.ZERO, laneDir);
String id = null;
if (!gtus.containsKey(id))
{
// NOTE: USE SEPARATE IDS HERE
gtus.put(id, new GtuData(id, nodeSupplier.apply(id), nodeSupplier.apply(id), gtuTypeSupplier.apply(id),
routeSupplier.apply(id)));
}
GtuData gtuData = gtus.get(id);
Trajectory> trajectory = new Trajectory(gtuData, metaData, extendedDataTypes, kpiLaneDirection);
// TODO: set data from outside
trajectory.add(position, speed, acceleration, time, gtu);
KpiLaneDirection laneDir = null;
((TrajectoryGroup) samplerData.trajectories.computeIfAbsent(laneDir, groupFunction)).addTrajectory(trajectory);
return samplerData;
*/
return null;
}
/**
* Returns a value from the map. Creates a value if needed.
* @param id String; id of object (key in map)
* @param map Map<String, T>; stored values
* @param producer Supplier<TT>; producer used if no value exists in the map
* @param type
* @return value for the id
*/
private final T getOrCreate(final String id, final Map map, final Function producer)
{
if (!map.containsKey(id))
{
map.put(id, producer.apply(id));
}
return map.get(id);
}
// TABLE METHODS
/** {@inheritDoc} */
@Override
public Iterator iterator()
{
// TODO: local iterator over this.trajectories, trajectories per group, and length of each trajectory
// TODO: gathering the extended and filter data types should be done here, these are within the trajectories, and upon
// file loading, this should be mimicked
Iterator laneIterator = this.trajectories.keySet().iterator();
return new Iterator()
{
private Iterator> trajectoryIterator = laneIterator.hasNext() ? SamplerData.this.trajectories.get(
laneIterator.next()).iterator() : null;
private Trajectory trajectory = this.trajectoryIterator != null && this.trajectoryIterator.hasNext()
? this.trajectoryIterator.next() : null;
private Trajectory currentTrajectory;
private int index;
@Override
public boolean hasNext()
{
if (this.index == this.currentTrajectory.size())
{
// get next trajectory
}
return true;
}
@Override
public Record next()
{
Record record = new Record()
{
@Override
public T getValue(final Column column)
{
return null;
}
@Override
public Object getValue(final String id)
{
return null;
}
};
this.index++;
return record;
}
};
}
/** {@inheritDoc} */
@Override
public boolean isEmpty()
{
for (TrajectoryGroup group : this.trajectories.values())
{
for (Trajectory trajectory : group.getTrajectories())
{
if (trajectory.size() > 0)
{
return false;
}
}
}
return true;
}
// LOCAL HELPER CLASSES TO IMPLEMENT INTERFACES //
/**
* Getter for single {@code String} input.
* @param output value type
*/
private static class Getter
{
/** Map with cached values. */
private final Map map = new LinkedHashMap<>();
/** Provider function. */
private Function function;
/**
* Constructor.
* @param function Function<String, T>; provider function
*/
Getter(final Function function)
{
this.function = function;
}
/**
* Get value, from cache or provider function.
* @param id String; id
* @return T; value, from cache or provider function
*/
public T get(final String id)
{
T t;
if (!this.map.containsKey(id))
{
t = this.function.apply(id);
this.map.put(id, t);
}
else
{
t = this.map.get(id);
}
return t;
}
}
/**
* Getter for dual {@code String} and {@code O} input.
* @param type of second input (besides the first being {@code String})
* @param output value type
*/
private static class BiGetter
{
/** Map with cached values. */
private final Map map = new LinkedHashMap<>();
/** Provider function. */
private BiFunction function;
/**
* Constructor.
* @param function BiFunction<String, T>; provider function
*/
BiGetter(final BiFunction function)
{
this.function = function;
}
/**
* Get value, from cache or provider function.
* @param id String; id
* @param o O; other object
* @return T; value, from cache or provider function
*/
public T get(final String id, final O o)
{
T t;
if (!this.map.containsKey(id))
{
t = this.function.apply(id, o);
this.map.put(id, t);
}
else
{
t = this.map.get(id);
}
return t;
}
}
/** Helper class LinkData. */
private static class LinkData implements LinkDataInterface
{
/** Length ({@code null} always). */
private final Length length = null; // unknown in this context
/** Id. */
private final String id;
/** Lanes. */
private final List lanes = new ArrayList<>();
/**
* @param id String; id
*/
LinkData(final String id)
{
this.id = id;
}
/** {@inheritDoc} */
@Override
public Length getLength()
{
return this.length;
}
/** {@inheritDoc} */
@Override
public List extends LaneDataInterface> getLaneDatas()
{
return this.lanes;
}
/** {@inheritDoc} */
@Override
public String getId()
{
return this.id;
}
}
/** Helper class LaneData. */
private static class LaneData implements LaneDataInterface
{
/** Length ({@code null} always). */
private final Length length = null; // unknown in this context
/** Id. */
private final String id;
/** Link. */
private final LinkData link;
/**
* Constructor.
* @param id String; id
* @param link LinkData; link
*/
@SuppressWarnings("synthetic-access")
LaneData(final String id, final LinkData link)
{
this.id = id;
this.link = link;
link.lanes.add(this);
}
/** {@inheritDoc} */
@Override
public Length getLength()
{
return this.length;
}
/** {@inheritDoc} */
@Override
public LinkData getLinkData()
{
return this.link;
}
/** {@inheritDoc} */
@Override
public String getId()
{
return this.id;
}
}
/** Helper class NodeData. */
private static class NodeData implements NodeDataInterface
{
/** Node id. */
private String id;
/**
* Constructor.
* @param id String; id
*/
NodeData(final String id)
{
this.id = id;
}
/** {@inheritDoc} */
@Override
public String getId()
{
return null;
}
}
/** Helper class GtuTypeData. */
private static class GtuTypeData implements GtuTypeDataInterface
{
/** Node id. */
private String id;
/**
* Constructor.
* @param id String; id
*/
GtuTypeData(final String id)
{
this.id = id;
}
/** {@inheritDoc} */
@Override
public String getId()
{
return null;
}
}
/** Helper class RouteData. */
private static class RouteData implements RouteDataInterface
{
/** Node id. */
private String id;
/**
* Constructor.
* @param id String; id
*/
RouteData(final String id)
{
this.id = id;
}
/** {@inheritDoc} */
@Override
public String getId()
{
return null;
}
}
/** Helper class GtuData. */
private static class GtuData implements GtuDataInterface
{
/** Id. */
private final String id;
/** Origin. */
private final NodeData origin;
/** Destination. */
private final NodeData destination;
/** GTU type. */
private final GtuTypeData gtuType;
/** Route. */
private final RouteData route;
/**
* @param id String; id
* @param origin NodeData; origin
* @param destination NodeData; destination
* @param gtuType GtuTypeData; GTU type
* @param route RouteData; route
*/
GtuData(final String id, final NodeData origin, final NodeData destination, final GtuTypeData gtuType,
final RouteData route)
{
this.id = id;
this.origin = origin;
this.destination = destination;
this.gtuType = gtuType;
this.route = route;
}
/** {@inheritDoc} */
@Override
public String getId()
{
return this.id;
}
/** {@inheritDoc} */
@Override
public NodeDataInterface getOriginNodeData()
{
return this.origin;
}
/** {@inheritDoc} */
@Override
public NodeDataInterface getDestinationNodeData()
{
return this.destination;
}
/** {@inheritDoc} */
@Override
public GtuTypeDataInterface getGtuTypeData()
{
return this.gtuType;
}
/** {@inheritDoc} */
@Override
public RouteDataInterface getRouteData()
{
return this.route;
}
}
}