/**
* 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.directio.hive.info;
import java.text.MessageFormat;
import java.util.Objects;
import com.asakusafw.directio.hive.syntax.HiveSyntax;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Represents Hive delimited text row format.
* @since 0.8.1
*/
public class DelimitedRowFormatInfo implements RowFormatInfo {
private static final String K_LINE_SEPARATOR = "line";
private static final String K_FIELD_SEPARATOR = "field";
private static final String K_FIELD_SEPARATOR_ESCAPE = "escape";
private static final String K_COLLECTION_ITEM_SEPARATOR = "item";
private static final String K_MAP_PAIR_SEPARATOR = "pair";
private static final String K_NULL_SYMBOL = "null";
private final String lineSeparator;
private final String fieldSeparator;
private final String fieldSeparatorEscape;
private final String collectionItemSeparator;
private final String mapPairSeparator;
private final String nullSymbol;
/**
* Creates a new instance.
* @param lineSeparator the line separator character
* @param fieldSeparator the field separator character
* @param fieldSeparatorEscape the escape character (for field separators)
* @param collectionItemSeparator the collection item separator character
* @param mapPairSeparator the map key-value separator character
* @param nullSymbol the {@code null} symbol character
*/
@JsonCreator
public DelimitedRowFormatInfo(
@JsonProperty(value = K_LINE_SEPARATOR, required = false) String lineSeparator,
@JsonProperty(value = K_FIELD_SEPARATOR, required = false) String fieldSeparator,
@JsonProperty(value = K_FIELD_SEPARATOR_ESCAPE, required = false) String fieldSeparatorEscape,
@JsonProperty(value = K_COLLECTION_ITEM_SEPARATOR, required = false) String collectionItemSeparator,
@JsonProperty(value = K_MAP_PAIR_SEPARATOR, required = false) String mapPairSeparator,
@JsonProperty(value = K_NULL_SYMBOL, required = false) String nullSymbol) {
this.lineSeparator = validate(lineSeparator);
this.fieldSeparator = validate(fieldSeparator);
this.fieldSeparatorEscape = validate(fieldSeparatorEscape);
this.collectionItemSeparator = validate(collectionItemSeparator);
this.mapPairSeparator = validate(mapPairSeparator);
this.nullSymbol = validate(nullSymbol);
}
private static String validate(String value) {
if (value == null || value.isEmpty()) {
return null;
}
if (value.length() >= 2) {
throw new IllegalArgumentException(MessageFormat.format(
"delimited text option must be a single character: {0}",
HiveSyntax.quoteLiteral('"', value)));
}
return value;
}
@JsonProperty("kind")
@Override
public FormatKind getFormatKind() {
return FormatKind.DELIMITED;
}
/**
* Returns the line separator character.
* @return the line separator character, or {@code null} if it is specified
*/
@JsonProperty(K_LINE_SEPARATOR)
public String getLineSeparator() {
return lineSeparator;
}
/**
* Returns the field separator character.
* @return the field separator character, or {@code null} if it is specified
*/
@JsonProperty(K_FIELD_SEPARATOR)
public String getFieldSeparator() {
return fieldSeparator;
}
/**
* Returns the escape character for the field separator.
* @return the escape character, or {@code null} if it is specified
*/
@JsonProperty(K_FIELD_SEPARATOR_ESCAPE)
public String getFieldSeparatorEscape() {
return fieldSeparatorEscape;
}
/**
* Returns the collection items terminator character.
* @return the collection items terminator character, or {@code null} if it is specified
*/
@JsonProperty(K_COLLECTION_ITEM_SEPARATOR)
public String getCollectionItemSeparator() {
return collectionItemSeparator;
}
/**
* Returns the map key terminator character.
* @return the map key terminator character, or {@code null} if it is specified
*/
@JsonProperty(K_MAP_PAIR_SEPARATOR)
public String getMapPairSeparator() {
return mapPairSeparator;
}
/**
* Returns the {@code null} character.
* @return the {@code null} character, or {@code null} if it is specified
*/
@JsonProperty(K_NULL_SYMBOL)
public String getNullSymbol() {
return nullSymbol;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Objects.hashCode(lineSeparator);
result = prime * result + Objects.hashCode(fieldSeparator);
result = prime * result + Objects.hashCode(fieldSeparatorEscape);
result = prime * result + Objects.hashCode(collectionItemSeparator);
result = prime * result + Objects.hashCode(mapPairSeparator);
result = prime * result + Objects.hashCode(nullSymbol);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
DelimitedRowFormatInfo other = (DelimitedRowFormatInfo) obj;
if (!Objects.equals(lineSeparator, other.lineSeparator)) {
return false;
}
if (!Objects.equals(fieldSeparator, other.fieldSeparator)) {
return false;
}
if (!Objects.equals(fieldSeparatorEscape, other.fieldSeparatorEscape)) {
return false;
}
if (!Objects.equals(collectionItemSeparator, other.collectionItemSeparator)) {
return false;
}
if (!Objects.equals(mapPairSeparator, other.mapPairSeparator)) {
return false;
}
if (!Objects.equals(nullSymbol, other.nullSymbol)) {
return false;
}
return true;
}
@Override
public String toString() {
return String.format(
"%s(line=%s, field=%s, escape=%s, collection=%s, map=%s, null=%s)", //$NON-NLS-1$
getFormatKind(),
toString(lineSeparator),
toString(fieldSeparator),
toString(fieldSeparatorEscape),
toString(collectionItemSeparator),
toString(mapPairSeparator),
toString(nullSymbol));
}
private static String toString(String value) {
if (value == null) {
return "N/A"; //$NON-NLS-1$
} else {
return HiveSyntax.quoteLiteral('\'', value);
}
}
/**
* A builder for {@link DelimitedRowFormatInfo}.
* @since 0.8.1
*/
public static class Builder {
private String lineSeparator;
private String fieldSeparator;
private String fieldSeparatorEscape;
private String collectionItemSeparator;
private String mapPairSeparator;
private String nullValue;
/**
* {@code FIELDS TERMINATED BY <c>}.
* @param c the character
* @return this
*/
public Builder fieldsTerminatedBy(char c) {
this.fieldSeparator = String.valueOf(c);
return this;
}
/**
* {@code FIELDS TERMINATED .. ESCAPED BY <c>}.
* @param c the character
* @return this
*/
public Builder escapedBy(char c) {
this.fieldSeparatorEscape = String.valueOf(c);
return this;
}
/**
* {@code COLLECTION ITEMS TERMINATED BY <c>}.
* @param c the character
* @return this
*/
public Builder collectionItemsTerminatedBy(char c) {
this.collectionItemSeparator = String.valueOf(c);
return this;
}
/**
* {@code MAP KEYS TERMINATED BY <c>}.
* @param c the character
* @return this
*/
public Builder mapKeysTerminatedBy(char c) {
this.mapPairSeparator = String.valueOf(c);
return this;
}
/**
* {@code LINES TERMINATED BY <c>}.
* @param c the character
* @return this
*/
public Builder linesTerminatedBy(char c) {
this.lineSeparator = String.valueOf(c);
return this;
}
/**
* {@code NULL DEFINED AS <c>}.
* @param c the character
* @return this
*/
public Builder nullDefinedAs(char c) {
this.nullValue = String.valueOf(c);
return this;
}
/**
* Builds an object.
* @return the built object
*/
public DelimitedRowFormatInfo build() {
return new DelimitedRowFormatInfo(
lineSeparator,
fieldSeparator, fieldSeparatorEscape,
collectionItemSeparator, mapPairSeparator,
nullValue);
}
}
}