org.pepstock.charba.client.data.Dataset Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of charba Show documentation
Show all versions of charba Show documentation
Charba, GWT Chart library based on CHART.JS
/**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.pepstock.charba.client.data;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.pepstock.charba.client.Defaults;
import org.pepstock.charba.client.Type;
import org.pepstock.charba.client.callbacks.ColorCallback;
import org.pepstock.charba.client.callbacks.DatasetContext;
import org.pepstock.charba.client.callbacks.JoinStyleCallback;
import org.pepstock.charba.client.callbacks.NativeCallback;
import org.pepstock.charba.client.callbacks.Scriptable;
import org.pepstock.charba.client.callbacks.ScriptableFunctions.ProxyIntegerCallback;
import org.pepstock.charba.client.callbacks.ScriptableFunctions.ProxyObjectCallback;
import org.pepstock.charba.client.callbacks.ScriptableIntegerChecker;
import org.pepstock.charba.client.callbacks.ScriptableUtil;
import org.pepstock.charba.client.callbacks.WidthCallback;
import org.pepstock.charba.client.colors.Gradient;
import org.pepstock.charba.client.colors.Pattern;
import org.pepstock.charba.client.commons.AbstractNode;
import org.pepstock.charba.client.commons.Array;
import org.pepstock.charba.client.commons.ArrayDouble;
import org.pepstock.charba.client.commons.ArrayDoubleList;
import org.pepstock.charba.client.commons.ArrayListHelper;
import org.pepstock.charba.client.commons.ArrayObject;
import org.pepstock.charba.client.commons.ArrayObjectContainerList;
import org.pepstock.charba.client.commons.CallbackProxy;
import org.pepstock.charba.client.commons.Constants;
import org.pepstock.charba.client.commons.HasCallbackScope;
import org.pepstock.charba.client.commons.JsHelper;
import org.pepstock.charba.client.commons.Key;
import org.pepstock.charba.client.commons.NativeObject;
import org.pepstock.charba.client.commons.NativeObjectContainerFactory;
import org.pepstock.charba.client.commons.ObjectType;
import org.pepstock.charba.client.defaults.IsDefaultOptions;
import org.pepstock.charba.client.defaults.IsDefaultTypedDataset;
import org.pepstock.charba.client.dom.elements.CanvasPatternItem;
import org.pepstock.charba.client.enums.DataType;
import org.pepstock.charba.client.enums.DefaultPluginId;
import org.pepstock.charba.client.enums.JoinStyle;
import org.pepstock.charba.client.items.Undefined;
import org.pepstock.charba.client.options.AnimationContainer;
import org.pepstock.charba.client.options.HasAnimationOptions;
import org.pepstock.charba.client.plugins.AbstractPluginOptions;
import org.pepstock.charba.client.plugins.AbstractPluginOptionsFactory;
import org.pepstock.charba.client.plugins.PluginIdChecker;
import org.pepstock.charba.client.utils.JSON;
/**
* The chart allows a number of properties to be specified for each data set. These are used to set display properties for a specific data set.
* This is the base implementation for all data sets with common fields.
*
* @author Andrea "Stock" Stocchero
*/
public abstract class Dataset extends AbstractNode implements HasDataset, HasAnimationOptions, HasCallbackScope {
// ---------------------------
// -- CALLBACKS PROXIES ---
// ---------------------------
// callback proxy to invoke the background color function
private final CallbackProxy backgroundColorCallbackProxy = JsHelper.get().newCallbackProxy();
// callback proxy to invoke the border color function
private final CallbackProxy borderColorCallbackProxy = JsHelper.get().newCallbackProxy();
// callback proxy to invoke the border width function
private final CallbackProxy borderWidthCallbackProxy = JsHelper.get().newCallbackProxy();
// callback proxy to invoke the hover background color function
private final CallbackProxy hoverBackgroundColorCallbackProxy = JsHelper.get().newCallbackProxy();
// callback proxy to invoke the hover border color function
private final CallbackProxy hoverBorderColorCallbackProxy = JsHelper.get().newCallbackProxy();
// callback proxy to invoke the hover border width function
private final CallbackProxy hoverBorderWidthCallbackProxy = JsHelper.get().newCallbackProxy();
// hover background color callback instance
private ColorCallback hoverBackgroundColorCallback = null;
// hover border color callback instance
private ColorCallback hoverBorderColorCallback = null;
// hover borderWidth callback instance
private WidthCallback hoverBorderWidthCallback = null;
// background color callback instance
private ColorCallback backgroundColorCallback = null;
// border color callback instance
private ColorCallback borderColorCallback = null;
// borderWidth callback instance
private WidthCallback borderWidthCallback = null;
// internal count
private static final AtomicInteger COUNTER = new AtomicInteger(0);
// default for hidden property
protected static final boolean DEFAULT_HIDDEN = false;
// default for parsing property
protected static final boolean DEFAULT_PARSING = true;
// default for normalized property
protected static final boolean DEFAULT_NORMALIZED = false;
// factory to create data points
static final DataPointFactory DATAPOINTS_FACTORY = new DataPointFactory();
// factory to create time series items
static final TimeSeriesItemFactory TIMESERIES_ITEMS_FACTORY = new TimeSeriesItemFactory();
// exception message when it's not using data points
static final String DATA_USAGE_MESSAGE = "Use datapoints instead of data for this dataset";
// exception string message for setting ore getting data
static final String TIME_SERIES_DATA_USAGE_MESSAGE = "setData and getData methods are not invokable by a time series chart";
// patterns container
private final PatternsContainer patternsContainer;
// gradients container
private final GradientsContainer gradientsContainer;
// cache for gradients created by callback
// K = key + data set locator, V = gradient
private final Map callbackGradientsContainer = new HashMap<>();
// cache for patterns created by callback
// K = key + data set locator, V = pattern
private final Map callbackPatternsContainer = new HashMap<>();
// default options values
private final IsDefaultOptions defaultValues;
// chart type related to data set
private final Type type;
// scope instance
private final String scope;
// animation container
private final AnimationContainer animationContainer;
// internal comparator to sort time series items
private static final Comparator COMPARATOR = (TimeSeriesItem o1, TimeSeriesItem o2) -> o1.getTime().compareTo(o2.getTime());
/**
* Name of common properties of native object related to a dataset.
*/
protected enum CanvasObjectProperty implements CanvasObjectKey
{
BACKGROUND_COLOR("backgroundColor", true),
BORDER_COLOR("borderColor", false),
HOVER_BACKGROUND_COLOR("hoverBackgroundColor", true),
HOVER_BORDER_COLOR("hoverBorderColor", false);
// name value of property
private final String value;
// flag for managing patterns
private final boolean hasPattern;
/**
* Creates with the property value to use in the native object.
*
* @param value value of property name
* @param hasPattern true
is able to manage also {@link Pattern} or {@link CanvasPatternItem}, otherwise it skips them
*/
private CanvasObjectProperty(String value, boolean hasPattern) {
this.value = value;
this.hasPattern = hasPattern;
}
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.commons.Key#value()
*/
@Override
public String value() {
return value;
}
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.data.Dataset.CanvasObjectKey#hasPattern()
*/
@Override
public boolean hasPattern() {
return hasPattern;
}
}
/**
* Name of common properties of native object related to a dataset.
*/
protected enum CommonProperty implements Key
{
CLIP("clip"),
DATA("data"),
BORDER_WIDTH("borderWidth"),
HOVER_BORDER_WIDTH("hoverBorderWidth");
// name value of property
private final String value;
/**
* Creates with the property value to use in the native object.
*
* @param value value of property name
*/
private CommonProperty(String value) {
this.value = value;
}
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.commons.Key#value()
*/
@Override
public String value() {
return value;
}
}
/**
* Name of private properties of native object.
*/
enum InternalProperty implements Key
{
ANIMATION("animation"),
LABEL("label"),
TYPE("type"),
HIDDEN("hidden"),
PARSING("parsing"),
NORMALIZED("normalized"),
// internal key to store a unique id
CHARBA_ID("charbaId"),
// internal key to store patterns and gradients
CHARBA_PATTERNS("charbaPatterns"),
CHARBA_GRADIENTS("charbaGradients"),
// internal key to store data type
CHARBA_DATA_TYPE("charbaDataType");
// name value of property
private final String value;
/**
* Creates with the property value to use in the native object.
*
* @param value value of property name
*/
private InternalProperty(String value) {
this.value = value;
}
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.commons.Key#value()
*/
@Override
public String value() {
return value;
}
}
/**
* Creates the data set using a default and chart type related to the data set, adding patterns and gradients element.
*
* @param type chart type related to the data set
* @param defaultValues default options
* @param hidden if true
, it will be initially hidden.
*/
protected Dataset(Type type, IsDefaultOptions defaultValues, boolean hidden) {
super(null);
this.defaultValues = defaultValues == null ? Defaults.get().getOptions(Type.checkAndGetIfValid(type)) : defaultValues;
// creates scope, checking form default
this.scope = createScope(getId());
// sets animation container
this.animationContainer = new AnimationContainer(getDefaultValues(), new DataEnvelop<>(getNativeObject()), this.scope);
// stores the type
this.type = type;
// stores the type
setValue(InternalProperty.TYPE, type);
// checks and stores visibility
if (hidden) {
// stores visibility
setHidden(hidden);
}
// patterns container
this.patternsContainer = new PatternsContainer(this);
// gradients container
this.gradientsContainer = new GradientsContainer(this);
// stores the id based on a counter
setValue(InternalProperty.CHARBA_ID, COUNTER.getAndIncrement());
// sets the Charba containers in the data set java script configuration
setValue(InternalProperty.CHARBA_PATTERNS, patternsContainer);
setValue(InternalProperty.CHARBA_GRADIENTS, gradientsContainer);
// sets default data type
setValue(InternalProperty.CHARBA_DATA_TYPE, DataType.UNKNOWN);
// -------------------------------
// -- SET CALLBACKS to PROXIES ---
// -------------------------------
// sets function to proxy callback in order to invoke the java interface
this.backgroundColorCallbackProxy.setCallback(context -> invokeColorCallback(createContext(context), getBackgroundColorCallback(), CanvasObjectProperty.BACKGROUND_COLOR, getDefaultBackgroundColorAsString()));
// sets function to proxy callback in order to invoke the java interface
this.borderColorCallbackProxy.setCallback(context -> invokeColorCallback(createContext(context), getBorderColorCallback(), CanvasObjectProperty.BORDER_COLOR, getDefaultBorderColorAsString()));
// sets function to proxy callback in order to invoke the java interface
this.borderWidthCallbackProxy.setCallback(context -> ScriptableUtil.getOptionValueAsNumber(createContext(context), borderWidthCallback, getDefaultBorderWidth(), ScriptableIntegerChecker.POSITIVE_OR_DEFAULT).intValue());
// sets function to proxy callback in order to invoke the java interface
this.hoverBackgroundColorCallbackProxy.setCallback(context -> invokeColorCallback(createContext(context), getHoverBackgroundColorCallback(), CanvasObjectProperty.HOVER_BACKGROUND_COLOR, getDefaultBackgroundColorAsString()));
// sets function to proxy callback in order to invoke the java interface
this.hoverBorderColorCallbackProxy.setCallback(context -> invokeColorCallback(createContext(context), getHoverBorderColorCallback(), CanvasObjectProperty.HOVER_BORDER_COLOR, getDefaultBorderColorAsString()));
// sets function to proxy callback in order to invoke the java interface
this.hoverBorderWidthCallbackProxy.setCallback(context -> ScriptableUtil.getOptionValueAsNumber(createContext(context), hoverBorderWidthCallback, getDefaultBorderWidth(), ScriptableIntegerChecker.POSITIVE_OR_DEFAULT).intValue());
}
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.options.HasAnimation#getAnimationContainer()
*/
@Override
public final AnimationContainer getAnimationContainer() {
return animationContainer;
}
/**
* Returns the amount of data.
*
* @return the amount of data
*/
public final int getDataCount() {
// gets the array
Array array = getArrayValue(CommonProperty.DATA);
// returns the length
return array != null ? array.length() : 0;
}
/**
* Returns the unique id of data sets.
*
* @return the unique id of data sets
*/
public final int getId() {
return getValue(InternalProperty.CHARBA_ID, Undefined.INTEGER);
}
/**
* Returns the scope of the data set, which is the options are used for defaults, chart defaults or chart.
*
* @return the scope of the data set
*/
@Override
public final String getScope() {
return scope;
}
/**
* Returns the data type of data sets.
*
* @return the data type of data sets
*/
public final DataType getDataType() {
return getValue(InternalProperty.CHARBA_DATA_TYPE, DataType.values(), DataType.UNKNOWN);
}
/**
* Returns the patterns container element.
*
* @return the patterns container
*/
final PatternsContainer getPatternsContainer() {
return patternsContainer;
}
/**
* Returns the gradients container element.
*
* @return the gradients container
*/
final GradientsContainer getGradientsContainer() {
return gradientsContainer;
}
/**
* Returns the default options instance.
*
* @return the default options instance.
*/
protected final IsDefaultOptions getDefaultValues() {
return defaultValues;
}
/**
* Returns the typed data set for the type of the data set.
*
* @return the typed data set for the type of the data set
*/
protected final IsDefaultTypedDataset getTypedDataset() {
return getDefaultValues().getDatasets().get(getType());
}
/**
* Returns true
if the color (selected by its property name) is not both a gradient not a pattern, otherwise false
.
*
* @param key property name to check
* @return true
if the color (selected by its property name) is not both a gradient not a pattern.
*/
final boolean hasColors(Key key) {
return !getPatternsContainer().hasObjects(key) && !getGradientsContainer().hasObjects(key);
}
/**
* Returns true
if the color (selected by its property name) is a pattern, otherwise false
.
*
* @param key property name to check
* @return true
if the color (selected by its property name) is a pattern.
*/
final boolean hasPatterns(Key key) {
return getPatternsContainer().hasObjects(key);
}
/**
* Returns true
if the color (selected by its property name) is a gradient, otherwise false
.
*
* @param key property name to check
* @return true
if the color (selected by its property name) is a gradient.
*/
final boolean hasGradients(Key key) {
return getGradientsContainer().hasObjects(key);
}
/**
* Removes the property key related to the color from pattern and gradient container if color is selected.
*
* @param key key property name to remove.
*/
final void resetBeingColors(Key key) {
// remove from patterns
getPatternsContainer().removeObjects(key);
// remove from gradients
getGradientsContainer().removeObjects(key);
}
/**
* Removes the property key related to the color from data set object and gradient container if pattern is selected.
*
* @param key key property name to remove.
*/
final void resetBeingPatterns(Key key) {
// removes color key from data set object
remove(key);
// remove from gradients
getGradientsContainer().removeObjects(key);
// here must be stored!!
setValue(key, getPatternsContainer().getProxy(key));
}
/**
* Removes the property key related to the color from data set object and pattern container if gradient is selected.
*
* @param key key property name to remove.
*/
final void resetBeingGradients(Key key) {
// removes color key from data set object
remove(key);
// remove from patterns
getPatternsContainer().removeObjects(key);
// here must be stored!!
setValue(key, getGradientsContainer().getProxy(key));
}
/**
* Removes the property key related to the color from data set object and pattern and gradient containers if callback is selected.
*
* @param key key property name to remove.
*/
final void resetBeingCallback(Key key) {
// removes color key from data set object
remove(key);
// remove from patterns
getPatternsContainer().removeObjects(key);
// remove from gradients
getGradientsContainer().removeObjects(key);
}
// -----------------
// CALLBACK
// -----------------
/**
* Returns the background color callback, if set, otherwise null
.
*
* @return the background color callback, if set, otherwise null
.
*/
public ColorCallback getBackgroundColorCallback() {
return backgroundColorCallback;
}
/**
* Sets the background color callback.
*
* @param backgroundColorCallback the background color callback.
*/
public void setBackgroundColor(ColorCallback backgroundColorCallback) {
// sets the callback
this.backgroundColorCallback = backgroundColorCallback;
// checks if callback is consistent
if (backgroundColorCallback != null) {
// resets previous setting
resetBeingCallback(CanvasObjectProperty.BACKGROUND_COLOR);
// adds the callback proxy function to java script object
setValue(CanvasObjectProperty.BACKGROUND_COLOR, backgroundColorCallbackProxy.getProxy());
} else {
// otherwise sets null which removes the properties from java script object
remove(CanvasObjectProperty.BACKGROUND_COLOR);
}
}
/**
* Sets the background color callback.
*
* @param backgroundColorCallback the background color callback.
*/
public void setBackgroundColor(NativeCallback backgroundColorCallback) {
// resets callback
setBackgroundColor((ColorCallback) null);
// resets previous setting
resetBeingCallback(CanvasObjectProperty.BACKGROUND_COLOR);
// stores value
setValue(CanvasObjectProperty.BACKGROUND_COLOR, backgroundColorCallback);
}
/**
* Returns the border color callback, if set, otherwise null
.
*
* @return the border color callback, if set, otherwise null
.
*/
public ColorCallback getBorderColorCallback() {
return borderColorCallback;
}
/**
* Sets the border color callback.
*
* @param borderColorCallback the border color callback.
*/
public void setBorderColor(ColorCallback borderColorCallback) {
// sets the callback
this.borderColorCallback = borderColorCallback;
// checks if callback is consistent
if (borderColorCallback != null) {
// resets previous setting
resetBeingCallback(CanvasObjectProperty.BORDER_COLOR);
// adds the callback proxy function to java script object
setValue(CanvasObjectProperty.BORDER_COLOR, borderColorCallbackProxy.getProxy());
} else {
// otherwise sets null which removes the properties from java script object
remove(CanvasObjectProperty.BORDER_COLOR);
}
}
/**
* Sets the border color callback.
*
* @param borderColorCallback the border color callback.
*/
public void setBorderColor(NativeCallback borderColorCallback) {
// resets callback
setBorderColor((ColorCallback) null);
// resets previous setting
resetBeingCallback(CanvasObjectProperty.BORDER_COLOR);
// stores value
setValue(CanvasObjectProperty.BORDER_COLOR, borderColorCallback);
}
/**
* Returns the border width callback, if set, otherwise null
.
*
* @return the border width callback, if set, otherwise null
.
*/
final WidthCallback getInternalBorderWidthCallback() {
return borderWidthCallback;
}
/**
* Sets the border width callback.
*
* @param borderWidthCallback the border width callback to set
*/
final void setInternalBorderWidth(WidthCallback borderWidthCallback) {
// sets the callback
this.borderWidthCallback = borderWidthCallback;
// checks if callback is consistent
if (borderWidthCallback != null) {
// adds the callback proxy function to java script object
setValue(CommonProperty.BORDER_WIDTH, borderWidthCallbackProxy.getProxy());
} else {
// otherwise sets null which removes the properties from java script object
remove(CommonProperty.BORDER_WIDTH);
}
}
/**
* Sets the border width callback.
*
* @param borderWidthCallback the border width callback to set
*/
final void setInternalBorderWidth(NativeCallback borderWidthCallback) {
// checks if callback is consistent
if (borderWidthCallback != null) {
// adds the callback proxy function to java script object
setValue(CommonProperty.BORDER_WIDTH, borderWidthCallback);
} else {
// otherwise sets null which removes the properties from java script object
remove(CommonProperty.BORDER_WIDTH);
}
}
/**
* Creates a data set context for callback.
*
* @param context native context, passed by CHART.JS
* @return a data set context for callback
*/
protected final DatasetContext createContext(NativeObject context) {
return new DatasetContext(context);
}
/**
* Returns the hover background color callback, if set, otherwise null
.
*
* @return the hover background color callback, if set, otherwise null
.
*/
public ColorCallback getHoverBackgroundColorCallback() {
return hoverBackgroundColorCallback;
}
/**
* Sets the hover background color callback.
*
* @param hoverBackgroundColorCallback the hover background color callback.
*/
public void setHoverBackgroundColor(ColorCallback hoverBackgroundColorCallback) {
// sets the callback
this.hoverBackgroundColorCallback = hoverBackgroundColorCallback;
// checks if callback is consistent
if (hoverBackgroundColorCallback != null) {
// resets previous setting
resetBeingCallback(CanvasObjectProperty.HOVER_BACKGROUND_COLOR);
// adds the callback proxy function to java script object
setValue(CanvasObjectProperty.HOVER_BACKGROUND_COLOR, hoverBackgroundColorCallbackProxy.getProxy());
} else {
// otherwise sets null which removes the properties from java script object
remove(CanvasObjectProperty.HOVER_BACKGROUND_COLOR);
}
}
/**
* Sets the hover background color callback.
*
* @param hoverBackgroundColorCallback the hover background color callback.
*/
public void setHoverBackgroundColor(NativeCallback hoverBackgroundColorCallback) {
// resets callback
setHoverBackgroundColor((ColorCallback) null);
// resets previous setting
resetBeingCallback(CanvasObjectProperty.HOVER_BACKGROUND_COLOR);
// stores value
setValue(CanvasObjectProperty.HOVER_BACKGROUND_COLOR, hoverBackgroundColorCallback);
}
/**
* Returns the hover border color callback, if set, otherwise null
.
*
* @return the hover border color callback, if set, otherwise null
.
*/
public ColorCallback getHoverBorderColorCallback() {
return hoverBorderColorCallback;
}
/**
* Sets the hover border color callback.
*
* @param hoverBorderColorCallback the hover border color callback.
*/
public void setHoverBorderColor(ColorCallback hoverBorderColorCallback) {
// sets the callback
this.hoverBorderColorCallback = hoverBorderColorCallback;
// checks if callback is consistent
if (hoverBorderColorCallback != null) {
// resets previous setting
resetBeingCallback(CanvasObjectProperty.HOVER_BORDER_COLOR);
// adds the callback proxy function to java script object
setValue(CanvasObjectProperty.HOVER_BORDER_COLOR, hoverBorderColorCallbackProxy.getProxy());
} else {
// otherwise sets null which removes the properties from java script object
remove(CanvasObjectProperty.HOVER_BORDER_COLOR);
}
}
/**
* Sets the hover border color callback.
*
* @param hoverBorderColorCallback the hover border color callback.
*/
public void setHoverBorderColor(NativeCallback hoverBorderColorCallback) {
// resets callback
setHoverBorderColor((ColorCallback) null);
// resets previous setting
resetBeingCallback(CanvasObjectProperty.HOVER_BORDER_COLOR);
// stores value
setValue(CanvasObjectProperty.HOVER_BORDER_COLOR, hoverBorderColorCallback);
}
/**
* Returns the hover border width callback, if set, otherwise null
.
*
* @return the hover border width callback, if set, otherwise null
.
*/
final WidthCallback getInternalHoverBorderWidthCallback() {
return hoverBorderWidthCallback;
}
/**
* Sets the hover border width callback.
*
* @param hoverBorderWidthCallback the hover border width callback to set
*/
final void setInternalHoverBorderWidth(WidthCallback hoverBorderWidthCallback) {
// sets the callback
this.hoverBorderWidthCallback = hoverBorderWidthCallback;
// checks if callback is consistent
if (hoverBorderWidthCallback != null) {
// adds the callback proxy function to java script object
setValue(CommonProperty.HOVER_BORDER_WIDTH, hoverBorderWidthCallbackProxy.getProxy());
} else {
// otherwise sets null which removes the properties from java script object
remove(CommonProperty.HOVER_BORDER_WIDTH);
}
}
/**
* Sets the hover border width callback.
*
* @param hoverBorderWidthCallback the hover border width callback to set
*/
final void setInternalHoverBorderWidth(NativeCallback hoverBorderWidthCallback) {
// checks if callback is consistent
if (hoverBorderWidthCallback != null) {
// adds the callback proxy function to java script object
setValue(CommonProperty.HOVER_BORDER_WIDTH, hoverBorderWidthCallback);
} else {
// otherwise sets null which removes the properties from java script object
remove(CommonProperty.HOVER_BORDER_WIDTH);
}
}
/**
* Returns the default background color value based on type of chart.
*
* @return the default background color value based on type of chart.
*/
protected String getDefaultBackgroundColorAsString() {
// returns the ARC default value because is MOSTLY used
return getDefaultValues().getElements().getArc().getBackgroundColorAsString();
}
/**
* Returns the default border color value based on type of chart.
*
* @return the default border color value based on type of chart.
*/
protected String getDefaultBorderColorAsString() {
// returns the ARC default value because is MOSTLY used
return getDefaultValues().getElements().getArc().getBorderColorAsString();
}
/**
* Returns the default border width value based on type of chart.
*
* @return the default border width value based on type of chart.
*/
protected int getDefaultBorderWidth() {
// returns the ARC default value because is MOSTLY used
return getDefaultValues().getElements().getArc().getBorderWidth();
}
/**
* Returns the default background color value based on type of chart.
*
* @return the default background color value based on type of chart.
*/
protected String getDefaultHoverBackgroundColorAsString() {
// returns the ARC default value because is MOSTLY used
return getDefaultValues().getElements().getArc().getBackgroundColorAsString();
}
/**
* Returns the default border color value based on type of chart.
*
* @return the default border color value based on type of chart.
*/
protected String getDefaultHoverBorderColorAsString() {
// returns the ARC default value because is MOSTLY used
return getDefaultValues().getElements().getArc().getBorderColorAsString();
}
/**
* Returns the default border width value based on type of chart.
*
* @return the default border width value based on type of chart.
*/
protected int getDefaultHoverBorderWidth() {
// returns the ARC default value because is MOSTLY used
return getDefaultValues().getElements().getArc().getBorderWidth();
}
/**
* Sets if the data set will appear or not.
*
* @param hidden if the data set will appear or not.
*/
protected final void setHidden(boolean hidden) {
// checks if is hidden
if (hidden) {
// then sets it
setValue(InternalProperty.HIDDEN, hidden);
} else {
// if is not hidden
// remove the property
remove(InternalProperty.HIDDEN);
}
}
/**
* Returns if the data set at first drawing will appear or not.
*
* @return if the data set at first drawing will appear or not.
*/
public final boolean isHidden() {
return getValue(InternalProperty.HIDDEN, DEFAULT_HIDDEN);
}
/**
* Sets how to parse the data set.
* The parsing can be disabled by specifying parsing: false
at chart options or data set.
* If parsing is disabled, data must be sorted and in the formats the associated chart type and scales use internally.
*
* @param parsing how to parse the data set.
* The parsing can be disabled by specifying parsing: false
at chart options or data set.
* If parsing is disabled, data must be sorted and in the formats the associated chart type and scales use internally.
*/
public void setParsing(boolean parsing) {
// checks if is disabling parsing
if (!parsing) {
// then sets it
setValue(InternalProperty.PARSING, parsing);
} else {
// if is not parsing
// remove the property
remove(InternalProperty.PARSING);
}
}
/**
* Returns how to parse the data set.
* The parsing can be disabled by specifying parsing: false
at chart options or data set.
* If parsing is disabled, data must be sorted and in the formats the associated chart type and scales use internally.
*
* @return how to parse the data set.
* The parsing can be disabled by specifying parsing: false
at chart options or data set.
* If parsing is disabled, data must be sorted and in the formats the associated chart type and scales use internally.
*/
public boolean isParsing() {
return getValue(InternalProperty.PARSING, DEFAULT_PARSING);
}
/**
* Sets if you provide data with indices that are unique, sorted, and consistent across data sets and provide the normalized: true
option to let CHARBA know that
* you have done so.
*
* @param normalized if you provide data with indices that are unique, sorted, and consistent across data sets and provide the normalized: true
option to let
* CHARBA know that you have done so.
*/
public void setNormalized(boolean normalized) {
// checks if is activating normalized
if (normalized) {
// then sets it
setValue(InternalProperty.NORMALIZED, normalized);
} else {
// if is not normalized
// remove the property
remove(InternalProperty.NORMALIZED);
}
}
/**
* Returns if you provide data with indices that are unique, sorted, and consistent across data sets and provide the normalized: true
option to let CHARBA know
* that you have done so.
*
* @return if you provide data with indices that are unique, sorted, and consistent across data sets and provide the normalized: true
option to let CHARBA know
* that you have done so.
*/
public boolean isNormalized() {
return getValue(InternalProperty.NORMALIZED, DEFAULT_NORMALIZED);
}
/**
* Sets the label for the data set which appears in the legend and tooltips.
*
* @param label the label for the data set which appears in the legend and tooltips.
*/
public void setLabel(String label) {
setValue(InternalProperty.LABEL, label);
}
/**
* Returns the label for the data set which appears in the legend and tooltips.
*
* @return the label for the data set which appears in the legend and tooltips.
*/
public String getLabel() {
return getValue(InternalProperty.LABEL, Undefined.STRING);
}
/**
* Sets how to clip relative to the chart area.
* If false
allows overflow, otherwise true
clips that many pixels inside the chart area.
*
* @param clip If false
allows overflow, otherwise true
clips that many pixels inside the chart area.
*/
public void setClip(boolean clip) {
// sets value
setValue(CommonProperty.CLIP, clip);
}
/**
* Sets how to clip relative to the chart area.
* Positive value allows overflow, negative value clips that many pixels inside the chart area. 0 = clip at the chart area.
*
* @param clip positive value allows overflow, negative value clips that many pixels inside the chart area. 0 = clip at the chart area
*/
public void setClip(double clip) {
// sets value
setValue(CommonProperty.CLIP, clip);
}
/**
* Sets how to clip relative to the chart area, by an object which configures clipping per side.
* Positive value allows overflow, negative value clips that many pixels inside the chart area. 0 = clip at the chart area.
*
* @param clip object which configures clipping per side
*/
public void setClip(Clip clip) {
// sets value
setValue(CommonProperty.CLIP, clip);
}
/**
* Returns if clips relative to the chart area.
*
* @return true
if clips relative to the chart area.
*/
public boolean isClip() {
return getValue(CommonProperty.CLIP, Undefined.BOOLEAN);
}
/**
* Returns how to clip relative to the chart area.
* Positive value allows overflow, negative value clips that many pixels inside the chart area. 0 = clip at the chart area.
* If the clip was set by a {@link Clip} object or boolean, returns {@link Undefined#DOUBLE}.
*
* @return positive value allows overflow, negative value clips that many pixels inside the chart area. 0 = clip at the chart area.
* If the clip was set by a {@link Clip} object or boolean, returns {@link Undefined#DOUBLE}
*/
public double getClip() {
// checks if previously was set to a clip object or boolean
// therefore NaN
if (isType(CommonProperty.CLIP, ObjectType.OBJECT, ObjectType.BOOLEAN)) {
// if object returns NaN
return Undefined.DOUBLE;
}
// gets value as number
return getValue(CommonProperty.CLIP, Undefined.DOUBLE);
}
/**
* Returns how to clip relative to the chart area.
* Positive value allows overflow, negative value clips that many pixels inside the chart area. 0 = clip at the chart area.
* If the clip was NOT set by a {@link Clip} object, returns a {@link Clip} instance with the same values.
*
* @return clip positive value allows overflow, negative value clips that many pixels inside the chart area. 0 = clip at the chart area.
* If the clip was NOT set by a {@link Clip} object, returns a {@link Clip} instance with the same values.
*/
public Clip getClipAsObject() {
// checks if previously was set to a number
// therefore new object with the same values
if (isType(CommonProperty.CLIP, ObjectType.NUMBER, ObjectType.BOOLEAN)) {
// new object
// with the same value
return new Clip(getClip());
}
// creates new value with previous item
// if there is otherwise an empty object
return new Clip(getValue(CommonProperty.CLIP));
}
/**
* Returns true
if data set must use only data points otherwise false
.
* The data set which can set this capabilities, must override this method.
*
* @return true
if data set must use only data points otherwise false
*/
boolean mustUseDataPoints() {
return false;
}
/**
* Sets the data property of a data set for a chart is specified as an array of numbers.
* Each point in the data array corresponds to the label at the same index on the x axis.
*
* @param values an array of numbers
*/
public void setData(double... values) {
// checks if it can use data as double
checkIfDataPointsMustBeUsed();
// set value. If null, removes key and then..
setArrayValue(CommonProperty.DATA, ArrayDouble.fromOrNull(values));
// sets data type checking if the key exists
setValue(InternalProperty.CHARBA_DATA_TYPE, has(CommonProperty.DATA) ? DataType.NUMBERS : DataType.UNKNOWN);
}
/**
* Sets the data property of a data set for a chart is specified as a list of numbers.
* Each point in the data list corresponds to the label at the same index on the x axis.
*
* @param values list of numbers.
*/
public void setData(List values) {
// checks if it can use data as double
checkIfDataPointsMustBeUsed();
// set value. If null, removes key and then..
setArrayValue(CommonProperty.DATA, ArrayDouble.fromOrNull(values));
// sets data type checking if the key exists
setValue(InternalProperty.CHARBA_DATA_TYPE, has(CommonProperty.DATA) ? DataType.NUMBERS : DataType.UNKNOWN);
}
/**
* Returns the data property of a data set for a chart is specified as a list of numbers.
* Each point in the data list corresponds to the label at the same index on the x axis.
*
* @return list of numbers or an empty list of numbers if the data type is not {@link DataType#NUMBERS}.
*/
public List getData() {
return getData(false);
}
/**
* Returns the data property of a data set for a chart is specified as a list of numbers.
* Each point in the data list corresponds to the label at the same index on the x axis.
*
* @param binding if true
binds the new array list in the container
* @return list of numbers or an empty list of numbers if the data type is not {@link DataType#NUMBERS}.
*/
public List getData(boolean binding) {
// checks if it can use data as double
checkIfDataPointsMustBeUsed();
// checks if is a numbers data type
if (has(CommonProperty.DATA) && DataType.NUMBERS.equals(getDataType())) {
// returns numbers
ArrayDouble array = getArrayValue(CommonProperty.DATA);
// returns array
return ArrayListHelper.list(array);
}
// checks if wants to bind the array
if (binding) {
ArrayDoubleList result = new ArrayDoubleList();
// set value
setArrayValue(CommonProperty.DATA, ArrayDouble.fromOrEmpty(result));
// sets data type
setValue(InternalProperty.CHARBA_DATA_TYPE, DataType.NUMBERS);
// returns list
return result;
}
// returns an empty list
return Collections.emptyList();
}
/**
* Returns the data property of a data set for a chart is specified as an array of data points
*
* @param factory data point object factory
* @param binding if true
binds the new array list in the container
* @return a list of data points or an empty list of data points if the data type is not {@link DataType#POINTS}.
*/
final List getDataPoints(DataPointFactory factory, boolean binding) {
// checks if is a numbers data type
if (has(CommonProperty.DATA) && DataType.POINTS.equals(getDataType())) {
// gets array
ArrayObject array = getArrayValue(CommonProperty.DATA);
// returns points
return ArrayListHelper.list(array, factory);
}
// checks if wants to bind the array
if (binding) {
ArrayObjectContainerList result = new ArrayObjectContainerList<>();
// set value
setArrayValue(CommonProperty.DATA, ArrayObject.fromOrEmpty(result));
// sets data type
setValue(InternalProperty.CHARBA_DATA_TYPE, DataType.POINTS);
// returns list
return result;
}
// returns an empty list
return Collections.emptyList();
}
/**
* Sets the data property of a data set for a chart is specified as an array of data points.
*
* @param datapoints an array of data points
*/
final void setInternalDataPoints(DataPoint... datapoints) {
setArrayValue(CommonProperty.DATA, ArrayObject.fromOrNull(datapoints));
// sets data type checking if the key exists
setValue(InternalProperty.CHARBA_DATA_TYPE, has(CommonProperty.DATA) ? DataType.POINTS : DataType.UNKNOWN);
}
/**
* Sets the data property of a data set for a chart is specified as an array of data points.
*
* @param datapoints a list of data points
*/
final void setInternalDataPoints(List datapoints) {
setArrayValue(CommonProperty.DATA, ArrayObject.fromOrNull(datapoints));
// sets data type checking if the key exists
setValue(InternalProperty.CHARBA_DATA_TYPE, has(CommonProperty.DATA) ? DataType.POINTS : DataType.UNKNOWN);
}
/**
* Returns the data property of a data set for a chart is specified as an array of data points.
*
* @param factory data point object factory
* @param binding if true
binds the new array list in the container
* @return a list of data points or an empty list of data points if the data type is not {@link DataType#POINTS}.
*/
final List getTimeSeriesItems(TimeSeriesItemFactory factory, boolean binding) {
// checks if is a points data type
if (has(CommonProperty.DATA) && DataType.POINTS.equals(getDataType())) {
// gets array
ArrayObject array = getArrayValue(CommonProperty.DATA);
// returns points
return ArrayListHelper.list(array, factory);
}
// checks if wants to bind the array
if (binding) {
ArrayObjectContainerList result = new ArrayObjectContainerList<>();
// set value
setArrayValue(CommonProperty.DATA, ArrayObject.fromOrEmpty(result));
// sets data type
setValue(InternalProperty.CHARBA_DATA_TYPE, DataType.POINTS);
// returns list
return result;
}
// returns an empty list
return Collections.emptyList();
}
/**
* Sets the data property of a data set for a chart is specified as an array of time series item.
*
* @param timeSeriesItems an array of time series item
*/
final void setInternalTimeSeriesItems(TimeSeriesItem... timeSeriesItems) {
// checks if array is consistent
if (timeSeriesItems != null) {
Arrays.sort(timeSeriesItems, COMPARATOR);
}
setArrayValue(CommonProperty.DATA, ArrayObject.fromOrNull(timeSeriesItems));
// sets data type checking if the key exists
setValue(InternalProperty.CHARBA_DATA_TYPE, has(CommonProperty.DATA) ? DataType.POINTS : DataType.UNKNOWN);
}
/**
* Sets the data property of a data set for a chart is specified as an array of time series items.
*
* @param timeSeriesItems a list of time series items
*/
final void setInternalTimeSeriesItems(List timeSeriesItems) {
// checks if list is consistent
if (timeSeriesItems != null) {
Collections.sort(timeSeriesItems, COMPARATOR);
}
setArrayValue(CommonProperty.DATA, ArrayObject.fromOrNull(timeSeriesItems));
// sets data type checking if the key exists
setValue(InternalProperty.CHARBA_DATA_TYPE, has(CommonProperty.DATA) ? DataType.POINTS : DataType.UNKNOWN);
}
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.data.HasDataset#getDataset()
*/
@Override
public Dataset getDataset() {
return this;
}
/**
* Returns the type of data set, based on type of chart.
*
* @return type of data set.
*/
public final Type getType() {
return type;
}
/**
* Removes the plugin options.
*
* @param pluginId plugin id.
*/
public void removeOptions(String pluginId) {
// checks if there is a stored plugin options
if (hasOptions(pluginId)) {
// checks plugin ids
Key pluginIdKey = PluginIdChecker.key(pluginId);
// removes configuration if exists
remove(pluginIdKey);
}
}
/**
* Sets the plugin options.
*
* @param options plugin options used to configure the plugin
* @param type of plugin options to store
*/
public void setOptions(T options) {
// checks if options is consistent and not a default plugin
if (options != null && !DefaultPluginId.is(options.getPluginId())) {
// checks plugin ids
Key pluginIdKey = PluginIdChecker.key(options.getPluginId());
// stores configuration
setValue(pluginIdKey, options);
}
}
/**
* Sets the plugin data set configuration.
* If data set configuration options is null
, the configuration of plugin will be removed.
*
* @param pluginId plugin id.
* @param options options used to configure the plugin.
* Pass null
to remove the configuration if exist.
* @param type of plugin options to store
*/
public final void setOptions(String pluginId, T options) {
// checks is a default plugin
if (!DefaultPluginId.is(pluginId)) {
// if null, removes the configuration
if (options == null && !DefaultPluginId.is(pluginId)) {
// removes configuration if exists
remove(PluginIdChecker.key(pluginId));
} else {
// stores configuration
setValue(PluginIdChecker.key(pluginId), options);
}
}
}
/**
* Checks if there is any data set configuration for a specific plugin, by its id.
*
* @param pluginId plugin id.
* @return true
if there is an options, otherwise false
.
*/
public final boolean hasOptions(String pluginId) {
// checks if exists and is not a default plugin
return has(PluginIdChecker.key(pluginId)) && !DefaultPluginId.is(pluginId);
}
/**
* Returns the plugin data set configuration, if exist.
* It uses a factory instance to create a plugin options.
*
* @param pluginId plugin id.
* @param factory factory instance to create a plugin options.
* @param type of plugin options to return
* @return options instance used to configure the plugin or null
if factory is null
.
*/
public final T getOptions(String pluginId, AbstractPluginOptionsFactory factory) {
// checks if factory argument is consistent and not a default plugin
if (factory != null && !DefaultPluginId.is(pluginId)) {
// creates the options by the factory
return factory.create(getValue(PluginIdChecker.key(pluginId)), defaultValues.getPlugins());
}
// if here, factory is not consistent
return null;
}
/**
* Returns the plugin options, if exist.
* It uses a factory instance to create a plugin options.
* If factory argument is not consistent, null
is returned.
*
* @param factory factory instance to create a plugin options
* @param type of plugin options to return
* @return plugin options used to configure the plugin or an empty object if not exist.
* If factory argument is not consistent, null
is returned.
*/
public T getOptions(AbstractPluginOptionsFactory factory) {
// checks if factory is consistent and not a default plugin
if (factory != null && !DefaultPluginId.is(factory.getPluginId())) {
// creates the object using the defaults options
return factory.create(getValue(PluginIdChecker.key(factory.getPluginId())), defaultValues.getPlugins());
}
// if here factory is not consistent
return null;
}
/**
* Clears the cache of patterns and gradients created by callbacks.
*/
final void clearCallbackPatternsAndGradients() {
callbackGradientsContainer.clear();
callbackPatternsContainer.clear();
}
/**
* Clears the cache ONLY of gradients created by callbacks.
*/
final void resetCallbackGradients() {
callbackGradientsContainer.clear();
}
/**
* Returns the gradient configured by callback for a specific data set and data index, for a specific property.
*
* @param property property of data set which have stored the gradient
* @param datasetIndex data set index to get gradient
* @param index data index to get the gradient
* @return the gradient instance or null
if not defined
*/
final Gradient getCallbackGradient(Key property, int datasetIndex, int index) {
// checks consistency of key and if there is any gradient stored in cache
if (Key.isValid(property) && !callbackGradientsContainer.isEmpty()) {
// creates the key used to store the gradient
String key = createCallbackCanvasObjectKey(property, datasetIndex, index);
// access to cache to get the gradient by key
return callbackGradientsContainer.get(key);
}
// if here the arguments are not consistent
return null;
}
/**
* Returns the pattern configured by callback for a specific data set and data index, for a specific property.
*
* @param property property of data set which have stored the pattern
* @param datasetIndex data set index to get pattern
* @param index data index to get the pattern
* @return the pattern instance or null
if not defined
*/
final Pattern getCallbackPattern(Key property, int datasetIndex, int index) {
// checks consistency of key and if there is any pattern stored in cache
if (Key.isValid(property) && !callbackPatternsContainer.isEmpty()) {
// creates the key used to store the pattern
String key = createCallbackCanvasObjectKey(property, datasetIndex, index);
// access to cache to get the pattern by key
return callbackPatternsContainer.get(key);
}
// if here the arguments are not consistent
return null;
}
/**
* Returns a color value of property by a callback, checking all different types of object which can be used as value of the property in color ones.
*
* @param context scriptable context
* @param callback callback to invoke
* @param property property of data set used to store the color
* @param defaultValue default value to return in case of chart, callback or result of callback are not consistent.
* @return a value of property as color
*/
protected final Object invokeColorCallback(DatasetContext context, Scriptable, DatasetContext> callback, CanvasObjectKey property, String defaultValue) {
// checks if the context and chart are correct
if (context != null) {
// calls callback
Object result = callback.invoke(context);
if (result instanceof Gradient) {
String key = createCallbackCanvasObjectKey(property, context.getDatasetIndex(), context.getDataIndex());
Gradient gradient = (Gradient) result;
callbackGradientsContainer.put(key, gradient);
} else if (result instanceof Pattern) {
String key = createCallbackCanvasObjectKey(property, context.getDatasetIndex(), context.getDataIndex());
Pattern pattern = (Pattern) result;
callbackPatternsContainer.put(key, pattern);
}
return ScriptableUtil.handleCallbackResultAsColor(context, result, defaultValue, property.hasPattern());
}
// if here, chart, callback or result of callback are not consistent
return defaultValue;
}
/**
* Returns a unique key to store canvas objects, created by callbacks, in the a cache.
* The format is [property],[datasetIndex],[dataIndex]
.
*
* @param property property of data set
* @param datasetIndex data set index
* @param index data index
* @return the key to use to store canvas object in the cache
*/
private String createCallbackCanvasObjectKey(Key property, int datasetIndex, int index) {
// checks if property is consistent
Key.checkIfValid(property);
// creates a builder
StringBuilder sb = new StringBuilder();
// adds property value
sb.append(property.value()).append(Constants.COMMA);
// adds data set index getting the max with 0
// because where the data set is not defined, the value is integer min value
sb.append(Math.max(datasetIndex, 0)).append(Constants.COMMA);
// adds data index getting the max with 0
// because where the data set is not defined, the value is integer min value
sb.append(Math.max(index, 0));
return sb.toString();
}
/**
* Checks if it can use data as double.
*/
void checkIfDataPointsMustBeUsed() {
// checks if it can use data as double
if (mustUseDataPoints()) {
// if not, exception
throw new UnsupportedOperationException(DATA_USAGE_MESSAGE);
}
}
/**
* Returns the JSON representation of data set. This is used y canvas object handler to know if the data set has been changed.
*
* @return JSON representation of data set
*/
String toFilteredJSON() {
return JSON.stringifyNativeObject(getNativeObject(), -1);
}
/**
* Creates a key for the data set options.
* The format is the following:
*
* <dataset-[datasetId]>
*
* where data set id if is the id of the data set.
*
* @param id the id of data set
* @return a key for the data set options
*/
private static final String createScope(int id) {
// creates a string builder
StringBuilder sb = new StringBuilder("dataset-");
// formats the key and returns it
return sb.append(id).toString();
}
/**
* Returns a {@link JoinStyle} when the callback has been activated.
*
* @param context native object as context.
* @param borderJoinStyleCallback border join style callback instance
* @param defaultValue default value if callback returns an inconsistent result
* @return a object property value, as {@link JoinStyle}
*/
final String onBorderJoinStyle(DatasetContext context, JoinStyleCallback borderJoinStyleCallback, JoinStyle defaultValue) {
// gets value
JoinStyle result = ScriptableUtil.getOptionValue(context, borderJoinStyleCallback);
// checks result
if (result != null) {
return result.value();
}
// default result
return defaultValue.value();
}
/**
* Interface to map color property which can or can not manage {@link Pattern} or {@link CanvasPatternItem}.
*
* @author Andrea "Stock" Stocchero
*
*/
interface CanvasObjectKey extends Key {
/**
* Returns true
is able to manage also {@link Pattern} or {@link CanvasPatternItem}, otherwise it skips them.
*
* @return true
is able to manage also {@link Pattern} or {@link CanvasPatternItem}, otherwise it skips them
*/
boolean hasPattern();
}
/**
* Factory to create a data point from a native object, used for array container lists.
*
* @author Andrea "Stock" Stocchero
*/
private static class DataPointFactory implements NativeObjectContainerFactory {
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.commons.NativeObjectContainerFactory#create(org.pepstock.charba.client. commons.NativeObject)
*/
@Override
public DataPoint create(NativeObject nativeObject) {
return new DataPoint(nativeObject);
}
}
/**
* Factory to create a time series item from a native object, used for array container lists.
*
* @author Andrea "Stock" Stocchero
*/
private static class TimeSeriesItemFactory implements NativeObjectContainerFactory {
/*
* (non-Javadoc)
*
* @see org.pepstock.charba.client.commons.NativeObjectContainerFactory#create(org.pepstock.charba.client. commons.NativeObject)
*/
@Override
public TimeSeriesItem create(NativeObject nativeObject) {
return new TimeSeriesItem(nativeObject);
}
}
}