/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* Licensed 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 com.asakusafw.dmdl.directio.text;
import static com.asakusafw.dmdl.directio.text.TextFormatConstants.*;
import java.time.ZoneId;
import java.util.Map;
import com.asakusafw.dmdl.directio.util.ClassName;
import com.asakusafw.dmdl.directio.util.DatePattern;
import com.asakusafw.dmdl.directio.util.DecimalPattern;
import com.asakusafw.dmdl.directio.util.Value;
import com.asakusafw.dmdl.model.AstAttribute;
import com.asakusafw.dmdl.model.AstAttributeElement;
import com.asakusafw.dmdl.semantics.DmdlSemantics;
import com.asakusafw.runtime.io.text.csv.QuoteStyle;
import com.asakusafw.runtime.io.text.driver.ErrorAction;
import com.asakusafw.runtime.io.text.value.DecimalOptionFieldAdapter;
/**
* Settings of text fields.
* @since 0.9.1
*/
public class TextFieldSettings {
private Value<ClassName> adapterClass = Value.undefined();
private Value<String> nullFormat = Value.undefined();
private Value<String> trueFormat = Value.undefined();
private Value<String> falseFormat = Value.undefined();
private Value<DecimalPattern> numberFormat = Value.undefined();
private Value<DatePattern> dateFormat = Value.undefined();
private Value<DatePattern> dateTimeFormat = Value.undefined();
private Value<ZoneId> timeZone = Value.undefined();
private Value<DecimalOptionFieldAdapter.OutputStyle> decimalOutputStyle = Value.undefined();
private Value<Boolean> trimInputWhitespaces = Value.undefined();
private Value<Boolean> skipEmptyInput = Value.undefined();
private Value<ErrorAction> malformedInputAction = Value.undefined();
private Value<ErrorAction> unmappableOutputAction = Value.undefined();
private Value<QuoteStyle> quoteStyle = Value.undefined();
/**
* Returns the field adapter class.
* @return the adapter
*/
public Value<ClassName> getAdapterClass() {
return adapterClass;
}
/**
* Returns the string representation of {@code null}.
* @return the string representation of {@code null}
*/
public Value<String> getNullFormat() {
return nullFormat;
}
/**
* Returns the string representation of {@code true}.
* @return the string representation of {@code true}
*/
public Value<String> getTrueFormat() {
return trueFormat;
}
/**
* Returns the string representation of {@code false}.
* @return the string representation of {@code false}
*/
public Value<String> getFalseFormat() {
return falseFormat;
}
/**
* Returns the string representation of numbers.
* @return the string representation of numbers
*/
public Value<DecimalPattern> getNumberFormat() {
return numberFormat;
}
/**
* Returns the string representation of {@code DATE}.
* @return the string representation of {@code DATE}
*/
public Value<DatePattern> getDateFormat() {
return dateFormat;
}
/**
* Returns the string representation of {@code DATETIME}.
* @return the string representation of {@code DATETIME}
*/
public Value<DatePattern> getDateTimeFormat() {
return dateTimeFormat;
}
/**
* Returns the time zone.
* @return the time zone
*/
public Value<ZoneId> getTimeZone() {
return timeZone;
}
/**
* Returns the decimal output style.
* @return the decimal output style
*/
public Value<DecimalOptionFieldAdapter.OutputStyle> getDecimalOutputStyle() {
return decimalOutputStyle;
}
/**
* Returns whether or not trims input field leading/trailing white-space characters.
* @return {@code true} if trims input field leading/trailing white-space characters, otherwise {@code false}
*/
public Value<Boolean> getTrimInputWhitespaces() {
return trimInputWhitespaces;
}
/**
* Returns whether or not skips empty input field.
* @return {@code true} if skips empty input field, otherwise {@code false}
*/
public Value<Boolean> getSkipEmptyInput() {
return skipEmptyInput;
}
/**
* Returns the error action of malformed inputs.
* @return the error action of malformed inputs
*/
public Value<ErrorAction> getMalformedInputAction() {
return malformedInputAction;
}
/**
* Returns the error action of unmappable outputs.
* @return the error action of unmappable outputs
*/
public Value<ErrorAction> getUnmappableOutputAction() {
return unmappableOutputAction;
}
/**
* Returns the quote style.
* @return the quote style
*/
public Value<QuoteStyle> getQuoteStyle() {
return quoteStyle;
}
/**
* Consumes attribute elements about escape settings, and returns corresponding {@link EscapeSettings}.
* @param environment the current environment
* @param attribute the attribute
* @param elements the element map to be consumed
* @return corresponded {@link EscapeSettings}.
*/
public static TextFieldSettings consume(
DmdlSemantics environment, AstAttribute attribute,
Map<String, AstAttributeElement> elements) {
AttributeAnalyzer analyzer = new AttributeAnalyzer(environment, attribute);
TextFieldSettings settings = new TextFieldSettings();
consumeAdapterClass(settings, analyzer, elements.remove(ELEMENT_FIELD_ADAPTER));
consumeNullFormat(settings, analyzer, elements.remove(ELEMENT_NULL_FORMAT));
consumeTrueFormat(settings, analyzer, elements.remove(ELEMENT_TRUE_FORMAT));
consumeFalseFormat(settings, analyzer, elements.remove(ELEMENT_FALSE_FORMAT));
consumeNumberFormat(settings, analyzer, elements.remove(ELEMENT_NUMBER_FORMAT));
consumeDateFormat(settings, analyzer, elements.remove(ELEMENT_DATE_FORMAT));
consumeDateTimeFormat(settings, analyzer, elements.remove(ELEMENT_DATETIME_FORMAT));
consumeTimeZone(settings, analyzer, elements.remove(ELEMENT_TIME_ZONE));
consumeDecimalOutputStyle(settings, analyzer, elements.remove(ELEMENT_DECIMAL_OUTPUT_STYLE));
consumeTrimInputWhitespaces(settings, analyzer, elements.remove(ELEMENT_TRIM_INPUT_WHITESPACES));
consumeSkipEmptyInput(settings, analyzer, elements.remove(ELEMENT_SKIP_EMPTY_INPUT));
consumeMalformedInputAction(settings, analyzer, elements.remove(ELEMENT_MALFORMED_INPUT_ACTION));
consumeUnmappableOutputAction(settings, analyzer, elements.remove(ELEMENT_UNMAPPABLE_OUTPUT_ACTION));
consumeQuoteStyle(settings, analyzer, elements.remove(ELEMENT_QUOTE_STYLE));
return settings;
}
private static void consumeAdapterClass(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.adapterClass = analyzer.toClassName(element);
}
}
private static void consumeNullFormat(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.nullFormat = analyzer.toStringWithNull(element);
}
}
private static void consumeTrueFormat(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.trueFormat = analyzer.toString(element);
}
}
private static void consumeFalseFormat(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.falseFormat = analyzer.toString(element);
}
}
private static void consumeNumberFormat(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.numberFormat = analyzer.toDecimalPatternWithNull(element);
}
}
private static void consumeDateFormat(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.dateFormat = analyzer.toDatePattern(element);
}
}
private static void consumeDateTimeFormat(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.dateTimeFormat = analyzer.toDatePattern(element);
}
}
private static void consumeTimeZone(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.timeZone = analyzer.toZoneIdWithNull(element);
}
}
private static void consumeDecimalOutputStyle(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.decimalOutputStyle = analyzer.toEnumConstant(element, DecimalOptionFieldAdapter.OutputStyle.class);
}
}
private static void consumeTrimInputWhitespaces(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.trimInputWhitespaces = analyzer.toBoolean(element);
}
}
private static void consumeSkipEmptyInput(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.skipEmptyInput = analyzer.toBoolean(element);
}
}
private static void consumeMalformedInputAction(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.malformedInputAction = analyzer.toEnumConstant(element, ErrorAction.class);
}
}
private static void consumeUnmappableOutputAction(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.unmappableOutputAction = analyzer.toEnumConstant(element, ErrorAction.class);
}
}
private static void consumeQuoteStyle(
TextFieldSettings settings, AttributeAnalyzer analyzer, AstAttributeElement element) {
if (element != null) {
settings.quoteStyle = analyzer.toEnumConstant(element, QuoteStyle.class);
}
}
/**
* Verifies this settings.
* @param environment the current environment
* @param attribute the original attribute
* @return {@code true} if the settings seems valid, otherwise {@code false}
*/
public boolean verify(DmdlSemantics environment, AstAttribute attribute) {
AttributeAnalyzer analyzer = new AttributeAnalyzer(environment, attribute);
checkNotConflict(analyzer, trueFormat, nullFormat);
checkNotConflict(analyzer, falseFormat, nullFormat);
checkNotConflict(analyzer, falseFormat, trueFormat);
return analyzer.hasError() == false;
}
private static void checkNotConflict(AttributeAnalyzer analyzer, Value<?> a, Value<?> b) {
if (a.isPresent() && b.isPresent() && a.equals(b)) {
analyzer.error(a.getDeclaration(),
Messages.getString("TextFieldSettings.diagnosticConflictFormat"), //$NON-NLS-1$
b.getDeclaration().name);
}
}
}