package cz.cuni.mff.d3s.been.persistence.task; import cz.cuni.mff.d3s.been.bpk.BpkIdentifier; import cz.cuni.mff.d3s.been.core.persistence.NamedEntity; import cz.cuni.mff.d3s.been.core.persistence.TaskEntity; import cz.cuni.mff.d3s.been.core.persistence.EntityID; import cz.cuni.mff.d3s.been.core.task.TaskContextDescriptor; import cz.cuni.mff.d3s.been.core.task.TaskDescriptor; import cz.cuni.mff.d3s.been.persistence.DAOException; import cz.cuni.mff.d3s.been.persistence.QueryAnswer; import cz.cuni.mff.d3s.been.util.JSONUtils; import cz.cuni.mff.d3s.been.util.JsonException; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * Facade for creation of persistent wrappers for configuration objects * * @author darklight */ public final class PersistentDescriptors { private static final JSONUtils jsonUtils = JSONUtils.newInstance(); /** * Entity ID for task descriptors */ public static final EntityID TASK_DESCRIPTOR = new EntityID().withKind("descriptor").withGroup("task"); /** * EntityID for context descriptors */ public static final EntityID CONTEXT_DESCRIPTOR = new EntityID().withKind("descriptor").withGroup("context"); /** * Create a persistent {@link cz.cuni.mff.d3s.been.core.task.TaskDescriptor} wrapper. The descriptor needs to be accompanied by runtime IDs of the task for which this descriptor will be submitted. * * @param td {@link cz.cuni.mff.d3s.been.core.task.TaskDescriptor} to wrap * @param taskId ID of the task which is submitting this context descriptor * @param contextId ID of the context in which the submitting task is running * @param benchmarkId ID of the benchmark in which the submitting task is running * * @return A persistable {@link cz.cuni.mff.d3s.been.core.persistence.TaskEntity} wrapping provided {@link cz.cuni.mff.d3s.been.core.task.TaskContextDescriptor} */ public static TaskEntity wrapTaskDescriptor(TaskDescriptor td, String taskId, String contextId, String benchmarkId) { final PersistentTaskDescriptor wrap = new PersistentTaskDescriptor(); wrap.setDescriptor(td); setRuntimeIDs(wrap, taskId, contextId, benchmarkId); return wrap; } /** * Create a persistent {@link cz.cuni.mff.d3s.been.core.task.TaskContextDescriptor} wrapper. The descriptor needs to be accompanied by runtime IDs of the task for which this descriptor will be submitted. * * @param tcd {@link cz.cuni.mff.d3s.been.core.task.TaskContextDescriptor} to wrap * @param taskId ID of the task which is submitting this context descriptor * @param contextId ID of the context in which the submitting task is running * @param benchmarkId ID of the benchmark in which the submitting task is running * * @return A persistable {@link cz.cuni.mff.d3s.been.core.persistence.TaskEntity} wrapping provided {@link cz.cuni.mff.d3s.been.core.task.TaskContextDescriptor} */ public static TaskEntity wrapContextDescriptor(TaskContextDescriptor tcd, String taskId, String contextId, String benchmarkId) { final PersistentContextDescriptor wrap = new PersistentContextDescriptor(); wrap.setDescriptor(tcd); setRuntimeIDs(wrap, taskId, contextId, benchmarkId); return wrap; } /** * Unpack a data query answer into a {@link TaskDescriptor} * * @param answer Persistence answer * * @return The task descriptor * * @throws DAOException On persistence access failure or unmarshalling error */ public static TaskDescriptor unpackTaskDescriptor(QueryAnswer answer) throws DAOException { assertAnswerIsData(answer); return extractExactlyOneElement(answer.getData(), PersistentTaskDescriptor.class).getDescriptor(); } /** * Unpack a data query answer into a {@link TaskContextDescriptor} * * @param answer Persistence answer * * @return The context descriptor * * @throws DAOException On persistence access failure or unmarshalling error */ public static TaskContextDescriptor unpackContextDescriptor(QueryAnswer answer) throws DAOException { assertAnswerIsData(answer); return extractExactlyOneElement(answer.getData(), PersistentContextDescriptor.class).getDescriptor(); } /** * Serialize a BPK identifier into JSON. * * @param bpkIdentifier BPK identifier to serialize * * @return A JSON representation of the provided BPK identifier * * @throws DAOException When the <em>BPK</em> ID fails to serialize */ public static String serializeBpkId(BpkIdentifier bpkIdentifier) throws DAOException { try { synchronized (jsonUtils) { return jsonUtils.serialize(bpkIdentifier); } } catch (JsonException e) { throw new DAOException("Cannot serialize BPK identifier", e); } } private static <T> Collection<T> extractAllElements(Collection<String> jsonData, Class<T> unmarshalType) throws DAOException { if (jsonData.size() != 1) { throw new DAOException("Response doesn't contain exactly one element"); } try { synchronized (jsonUtils) { return jsonUtils.deserialize(jsonData, unmarshalType); } } catch (JsonException e) { throw new DAOException("Descriptor unmarshalling failed", e); } } private static <T> T extractExactlyOneElement(Collection<String> jsonData, Class<T> unmarshalType) throws DAOException { if (jsonData.size() != 1) { throw new DAOException("Response doesn't contain exactly one element"); } try { synchronized (jsonUtils) { final Collection<T> unmarshalled = jsonUtils.deserialize(jsonData, unmarshalType); return unmarshalled.iterator().next(); } } catch (JsonException e) { throw new DAOException("Descriptor unmarshalling failed", e); } } private static void assertAnswerIsData(QueryAnswer answer) throws DAOException { if (!answer.isCarryingData()) { throw new DAOException(String.format("No data in answer: %s", answer.getStatus().getDescription())); } } private static void setRuntimeIDs(TaskEntity to, String taskId, String contextId, String benchmarkId) { to.setTaskId(taskId); to.setContextId(contextId); to.setBenchmarkId(benchmarkId); } }