/*******************************************************************************
* Copyright (c) 2007, 2011 Association for Decentralized Information Management in
* Industry THTH ry.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
*******************************************************************************/
package org.simantics.history;
import org.simantics.databoard.Bindings;
import org.simantics.databoard.accessor.StreamAccessor;
import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.NumberBinding;
import org.simantics.databoard.binding.mutable.MutableVariant;
import org.simantics.databoard.util.Bean;
import org.simantics.history.impl.FlushPolicy;
import org.simantics.history.util.subscription.SubscriptionItem;
/**
* Collector manages recoding of variables to subscribed items.
*
* Single variable is typically recorded to multiple subscription items with
* different recording parameters. The variable source is identified with
* "variableId" field in historyItem (given at #addItem()).
*
* The actual collecting uses the following procedure:
* If same value repeats, or is considered repeating because of deadband or interval setting,
* then the values are packed in to a single entry (called value band).
*
* An entry can be represented with either (a) as ranged or as (b) non-ranged format.
* In ranged format, the entry represents multiple values from the datasource.
* There are fields such as: start time, end time, min, max value, first and last value.
*
* In non-ranged format, the entry represents a single sample from the datasource.
* The format is very simple (time, value). When same value repeats, two samples
* are written, one at the start of the new value, another at to represent the
* last entry with the same value. At run-time, the sample is forwarded in time.
*
* @author toni.kalajainen
*/
public interface Collector {
/**
* Get a snapshot of all the item configurations.
*
* Note, The resulting bean can be converted to {@link SubscriptionItem} or {@link HistoryAndCollectorItem}
* with {@link Bean#readAvailableFields(Bean)} method.
*
* Note, this bean also contains "collectorState" object.
*
* @return items
*/
SubscriptionItem[] getItems();
/**
* Subscribe an item.
*
* The item is opened when the collecting starts at {@link #beginStep(NumberBinding, Object)}.
*
* Collector requres these fields are required:
* o id - String
* o variableId - String
* o deadband - double
* o interval - double
* o gain - double
* o bias - double
* o enabled - boolean
*
* It is recommended to use {@link SubscriptionItem} or {@link HistoryAndCollectorItem}.
* Although you may use your own classes aslong as they have the fields and extend Bean.
*
* @param item
*/
void addItem(Bean item) throws HistoryException;
void addItems(Bean...item) throws HistoryException;
/**
* Remove the subscribed item from the collector.
*
* Item's CollectorState is written to the history's meta-data.
* "collectorState"-field is added if it did not exist.
*
* @param id
* @throws HistoryException
*/
void removeItem(String id) throws HistoryException;
/**
* Add or update subscription item.
*
* @param item
* @throws HistoryException
*/
void setItem(Bean item) throws HistoryException;
/**
* Get associated history manager
*
* @return history manager
*/
HistoryManager getHistory();
/**
* Get flush policy
*
* @return flush policy
*/
FlushPolicy getFlushPolicy();
/**
* Set flush policy
* @param flushPolicy
*/
void setFlushPolicy(FlushPolicy flushPolicy);
/**
* Begin a new time step.
*
* @param binding (for example {@link Bindings#DOUBLE})
* @param time
* @throws HistoryException
*/
void beginStep(NumberBinding binding, Object time) throws HistoryException;
/**
* Get current time
*
* @param binding
* @return
* @throws HistoryException
*/
Object getTime(Binding binding) throws HistoryException;
/**
* Set a value for a variable. If there are multiple items for one
* variable, the value is written to all streams.
*
* @param id
* @param binding
* @param value
* @throws HistoryException
*/
void setValue(String id, Binding binding, Object value) throws HistoryException;
/**
* Get the value the collector has about a variable.
*
* @param id
* @param binding in which to get result
* @return true if value existed
*/
Object getValue(String id, Binding binding) throws HistoryException;
boolean getValue(String id, MutableVariant result);
/**
* End the time step. Values are commited to history.
*
* @throws HistoryException
*/
void endStep() throws HistoryException;
/**
* Flush any pending changes to all time series.
*
* A few flush policies are, to flush after every step (not good
* performance), to flush on time interval, say, every second.
* And third, to flush after one second since last flush and step.
*
* @throws HistoryException
*/
void flush() throws HistoryException;
/**
* Save and Close the collector session.
* CollectorStates are written back to the history.
* "collectorState"-field is added if it did not exist.
*/
void close();
/**
* Open stream from associated history manager
*
* @param itemId
* @param mode
* @return accessor
* @throws HistoryException
*/
StreamAccessor openStream(String itemId, String mode) throws HistoryException;
/**
* Get the complete state of this collector as a bean. Required for
* supporting serialization of the internal collector state.
*
* Not intended to be thread-safe, i.e. do not invoke this while in a
* collection step.
*
* @return current collector state data
*/
Bean getState();
/**
* Required for supporting deserialization of the internal collector state.
* Do not invoke this during data collection. It is only intended for
* initializing a collector instance properly when a collector is used for
* appending to an existing history.
*
* @param newState
* a new complete state to set for this collector. Must be a
* value that's been previously retrieved from
* {@link #getCollectorState()}.
*/
void setState(Bean newState);
/**
* Allows history collector writers to optimize their invocations of the collector.
*
* @return true
if the this collector is enabled for collection or
* false
otherwise.
* @since 1.50.0, 1.35.3, 1.48.0.1
*/
default boolean isEnabled() {
return true;
}
}