/*******************************************************************************
* Copyright (c) 2016 Oak Ridge National Laboratory.
* 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:
* Xihui Chen - initial API and implementation
* Kay Kasemir - Comments, made immutable
* Bernhard Wedl - IMetaData
******************************************************************************/
package org.eclipse.nebula.visualization.xygraph.dataprovider;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* An (x,y) sample data with error.
* <p>
* The error values are absolute, positive numbers. For example, a Sample with
* Y=5, negative Y error 1 and positive Y error 2 represents a number of 5 that
* could also be anywhere in 4 .. 7. The errors are not percentages. The
* 'negative' error is actually a positive number.
* <p>
* Note: Only the x/y value is used in equals()! Error ranges and info texts are
* ignored when determining equality with another Sample.
*
* @author Xihui Chen
* @author Kay Kasemir Comments, made immutable
*/
public class Sample implements ISample, IMetaData {
final private double xValue;
final private double yValue;
final private double xPlusError;
final private double yPlusError;
final private double xMinusError;
final private double yMinusError;
final private String info;
private Object fMetaData;
private Map<String, Object> fMetaDataMap = new HashMap<String, Object>();
/**
* Initialize with x/y value
*
* @param xdata
* @param ydata
*/
public Sample(final double xdata, final double ydata) {
this(xdata, ydata, 0, 0, 0, 0, ""); //$NON-NLS-1$
}
/**
* Initialize with value and error range
*
* @param xValue
* @param yValue
* @param yPlusError
* @param yMinusError
* @param xPlusError
* @param xMinusError
*/
public Sample(final double xValue, final double yValue, final double yPlusError, final double yMinusError,
final double xPlusError, final double xMinusError) {
this(xValue, yValue, yPlusError, yMinusError, xPlusError, xMinusError, ""); //$NON-NLS-1$
}
/**
* Initialize with value, error ranges and info text
*
* @param xValue
* @param yValue
* @param yPlusError
* @param yMinusError
* @param xPlusError
* @param xMinusError
* @param info
*/
public Sample(final double xValue, final double yValue, final double yPlusError, final double yMinusError,
final double xPlusError, final double xMinusError, final String info) {
this.xValue = xValue;
this.yValue = yValue;
this.xPlusError = xPlusError;
this.yPlusError = yPlusError;
this.xMinusError = xMinusError;
this.yMinusError = yMinusError;
this.info = info;
}
/** @return X value */
public double getXValue() {
return xValue;
}
/** @return Y value */
public double getYValue() {
return yValue;
}
/** @return Negative X error. */
public double getXMinusError() {
return xMinusError;
}
/** @return Positive X error. */
public double getXPlusError() {
return xPlusError;
}
/** @return Negative Y error. */
public double getYMinusError() {
return yMinusError;
}
/** @return Positive Y error. */
public double getYPlusError() {
return yPlusError;
}
/** @return Sample info text. */
public String getInfo() {
return info;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((info == null) ? 0 : info.hashCode());
long temp;
temp = Double.doubleToLongBits(xMinusError);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(xPlusError);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(xValue);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(yMinusError);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(yPlusError);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(yValue);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Sample other = (Sample) obj;
if (info == null) {
if (other.info != null)
return false;
} else if (!info.equals(other.info))
return false;
if (Double.doubleToLongBits(xMinusError) != Double.doubleToLongBits(other.xMinusError))
return false;
if (Double.doubleToLongBits(xPlusError) != Double.doubleToLongBits(other.xPlusError))
return false;
if (Double.doubleToLongBits(xValue) != Double.doubleToLongBits(other.xValue))
return false;
if (Double.doubleToLongBits(yMinusError) != Double.doubleToLongBits(other.yMinusError))
return false;
if (Double.doubleToLongBits(yPlusError) != Double.doubleToLongBits(other.yPlusError))
return false;
if (Double.doubleToLongBits(yValue) != Double.doubleToLongBits(other.yValue))
return false;
return true;
}
/** @return String representation, mostly for debugging */
@SuppressWarnings("nls")
@Override
public String toString() {
final StringBuilder buf = new StringBuilder();
buf.append("(");
buf.append(xValue);
if (xMinusError != 0 || xPlusError != 0)
buf.append(" [-" + xMinusError + " ... +" + xPlusError + "]");
buf.append(", ");
buf.append(yValue);
if (yMinusError != 0 || yPlusError != 0)
buf.append(" [-" + yMinusError + " ... +" + yPlusError + "]");
if (info != null && info.length() > 0)
buf.append(", '" + info + "'");
buf.append(")");
return buf.toString();
}
@Override
public void setData(Object metaData) {
fMetaData = metaData;
}
@Override
public Object getData() {
return fMetaData;
}
@Override
public Object getData(String key) {
if (key == null)
throw new IllegalArgumentException("Key must not be null.");
return fMetaDataMap.get(key);
}
@Override
public void setData(String key, Object data) {
if (key == null)
throw new IllegalArgumentException("Key must not be null.");
if ((data == null) && (fMetaDataMap.containsKey(key)))
fMetaDataMap.remove(key);
else
fMetaDataMap.put(key, data);
}
@Override
public Map<String, Object> getDataCollection() {
return Collections.unmodifiableMap(fMetaDataMap);
}
}