/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008 Sun Microsystems, Inc.
* Portions Copyright 2014 ForgeRock AS
*/
package org.forgerock.opendj.config.dsconfig;
import static com.forgerock.opendj.dsconfig.DsconfigMessages.*;
import java.text.NumberFormat;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.opendj.config.BooleanPropertyDefinition;
import org.forgerock.opendj.config.DurationPropertyDefinition;
import org.forgerock.opendj.config.DurationUnit;
import org.forgerock.opendj.config.PropertyDefinition;
import org.forgerock.opendj.config.PropertyValueVisitor;
import org.forgerock.opendj.config.SizePropertyDefinition;
import org.forgerock.opendj.config.SizeUnit;
/**
* A class responsible for displaying property values. This class takes care of using locale specific formatting rules.
*/
final class PropertyValuePrinter {
/**
* Perform property type specific print formatting.
*/
private static final class MyPropertyValueVisitor extends PropertyValueVisitor<LocalizableMessage, Void> {
/**
* The requested size unit (null if the property's unit should be used).
*/
private final SizeUnit sizeUnit;
/**
* The requested time unit (null if the property's unit should be used).
*/
private final DurationUnit timeUnit;
/**
* Whether or not values should be displayed in a script-friendly manner.
*/
private final boolean isScriptFriendly;
/** The formatter to use for numeric values. */
private final NumberFormat numberFormat;
/** Private constructor. */
private MyPropertyValueVisitor(SizeUnit sizeUnit, DurationUnit timeUnit, boolean isScriptFriendly) {
this.sizeUnit = sizeUnit;
this.timeUnit = timeUnit;
this.isScriptFriendly = isScriptFriendly;
numberFormat = NumberFormat.getNumberInstance();
numberFormat.setGroupingUsed(!this.isScriptFriendly);
numberFormat.setMaximumFractionDigits(2);
}
/** {@inheritDoc} */
@Override
public LocalizableMessage visitBoolean(BooleanPropertyDefinition pd, Boolean v, Void p) {
return v ? INFO_VALUE_TRUE.get() : INFO_VALUE_FALSE.get();
}
/** {@inheritDoc} */
@Override
public LocalizableMessage visitDuration(DurationPropertyDefinition pd, Long v, Void p) {
if (pd.getUpperLimit() == null && (v < 0 || v == Long.MAX_VALUE)) {
return INFO_VALUE_UNLIMITED.get();
}
LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
long ms = pd.getBaseUnit().toMilliSeconds(v);
if (timeUnit == null && !isScriptFriendly && ms != 0) {
// Use human-readable string representation by default.
builder.append(DurationUnit.toString(ms));
} else {
// Use either the specified unit or the property definition's
// base unit.
DurationUnit unit = timeUnit;
if (unit == null) {
unit = pd.getBaseUnit();
}
builder.append(numberFormat.format(unit.fromMilliSeconds(ms)));
builder.append(' ');
builder.append(unit.getShortName());
}
return builder.toMessage();
}
/** {@inheritDoc} */
@Override
public LocalizableMessage visitSize(SizePropertyDefinition pd, Long v, Void p) {
if (pd.isAllowUnlimited() && v < 0) {
return INFO_VALUE_UNLIMITED.get();
}
SizeUnit unit = sizeUnit;
if (unit == null) {
if (isScriptFriendly) {
// Assume users want a more accurate value.
unit = SizeUnit.getBestFitUnitExact(v);
} else {
unit = SizeUnit.getBestFitUnit(v);
}
}
LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
builder.append(numberFormat.format(unit.fromBytes(v)));
builder.append(' ');
builder.append(unit.getShortName());
return builder.toMessage();
}
/** {@inheritDoc} */
@Override
public <T> LocalizableMessage visitUnknown(PropertyDefinition<T> pd, T v, Void p) {
// For all other property definition types the default encoding
// will do.
String s = pd.encodeValue(v);
if (isScriptFriendly) {
return LocalizableMessage.raw("%s", s);
} else if (s.trim().length() == 0 || s.contains(",")) {
// Quote empty strings or strings containing commas
// non-scripting mode.
return LocalizableMessage.raw("\"%s\"", s);
} else {
return LocalizableMessage.raw("%s", s);
}
}
}
/** The property value printer implementation. */
private final MyPropertyValueVisitor pimpl;
/**
* Creates a new property value printer.
*
* @param sizeUnit
* The user requested size unit or <code>null</code> if best-fit.
* @param timeUnit
* The user requested time unit or <code>null</code> if best-fit.
* @param isScriptFriendly
* If values should be displayed in a script friendly manner.
*/
public PropertyValuePrinter(SizeUnit sizeUnit, DurationUnit timeUnit, boolean isScriptFriendly) {
this.pimpl = new MyPropertyValueVisitor(sizeUnit, timeUnit, isScriptFriendly);
}
/**
* Print a property value according to the rules of this property value printer.
*
* @param <T>
* The type of property value.
* @param pd
* The property definition.
* @param value
* The property value.
* @return Returns the string representation of the property value encoded according to the rules of this property
* value printer.
*/
public <T> LocalizableMessage print(PropertyDefinition<T> pd, T value) {
return pd.accept(pimpl, value, null);
}
}