/*******************************************************************************
* Copyright (c) 2016 EfficiOS Inc., Jonathan Rajotte-Julien
*
* 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
*******************************************************************************/
package org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format;
import java.math.BigDecimal;
import java.text.FieldPosition;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat;
import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.viewers.LamiGraphRange;
/**
* Decimal formatter for Lami graph
*
* Since the graph use normalized internal value the initial (external)
* representation needs to be obtained. Subsequent formatting is done based on a
* Double. Loss of precision could occurs based on the size. For now, loss of
* precision for decimal values is not a big concern. If it ever become one the
* use of Long while formatting might come in handy.
*
* @author Jonathan Rajotte-Julien
*/
public class LamiDecimalUnitFormat extends DecimalUnitFormat {
/** Maximum amount of digits that can be represented into a double */
private static final int BIG_DECIMAL_DIVISION_SCALE = 22;
private static final long serialVersionUID = 977671266270661188L;
private final @Nullable LamiGraphRange fInternalRange;
private final @Nullable LamiGraphRange fExternalRange;
/**
* Default constructor
*/
public LamiDecimalUnitFormat() {
super();
fInternalRange = null;
fExternalRange = null;
}
/**
* Constructor with internal and external LamiRange for scale transformation
*
* @param internalRange
* The internal range used for graph representation
*
* @param externalRange
* The external (real value) range shown to the user
*/
public LamiDecimalUnitFormat(@Nullable LamiGraphRange internalRange, @Nullable LamiGraphRange externalRange) {
super();
fInternalRange = internalRange;
fExternalRange = externalRange;
}
/**
* Constructor with multiplication factor and internal and external
* LamiRange for scale transformation.
*
* @param factor
* Multiplication factor to apply to the value
* @param internalRange
* The internal range used for graph representation
* @param externalRange
* The external (real value) range shown to the user
*/
public LamiDecimalUnitFormat(double factor, @Nullable LamiGraphRange internalRange, @Nullable LamiGraphRange externalRange) {
super(factor);
fInternalRange = internalRange;
fExternalRange = externalRange;
}
/**
* @return the internal range definition
*/
public @Nullable LamiGraphRange getInternalRange() {
return fInternalRange;
}
/**
* @return the external range definition
*/
public @Nullable LamiGraphRange getExternalRange() {
return fExternalRange;
}
@Override
public StringBuffer format(@Nullable Object obj, @Nullable StringBuffer toAppendTo, @Nullable FieldPosition pos) {
if (!(obj instanceof Number) || toAppendTo == null) {
throw new IllegalArgumentException("Cannot format given Object as a Number: " + obj); //$NON-NLS-1$
}
@Nullable LamiGraphRange internalRange = fInternalRange;
@Nullable LamiGraphRange externalRange = fExternalRange;
if (internalRange == null || externalRange == null) {
StringBuffer buffer = super.format(obj, toAppendTo, pos);
return (buffer == null ? new StringBuffer() : buffer);
}
if (internalRange.getDelta().compareTo(BigDecimal.ZERO) == 0) {
StringBuffer buffer = super.format(externalRange.getMinimum().doubleValue(), toAppendTo, pos);
return (buffer == null ? new StringBuffer() : buffer);
}
if (externalRange.getDelta().compareTo(BigDecimal.ZERO) == 0) {
StringBuffer buffer = super.format(externalRange.getMinimum().doubleValue(), toAppendTo, pos);
return (buffer == null ? new StringBuffer() : buffer);
}
/* Find external value before formatting */
BigDecimal externalValue = (new BigDecimal(obj.toString()))
.subtract(internalRange.getMinimum())
.multiply(externalRange.getDelta())
.divide(internalRange.getDelta(), BIG_DECIMAL_DIVISION_SCALE, BigDecimal.ROUND_DOWN)
.add(externalRange.getMinimum());
Double value = externalValue.doubleValue();
StringBuffer buffer = super.format(value, toAppendTo, pos);
return (buffer == null ? new StringBuffer() : buffer);
}
}