blob: 36c8e536a516d526cbbc385c6028854d184da13d [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.sqoop.lib;
/**
* Encapsulates a set of delimiters used to encode a record.
*/
public class DelimiterSet implements Cloneable {
public static final char NULL_CHAR = '\000';
private char fieldDelim; // fields terminated by this.
private char recordDelim; // records terminated by this.
// If these next two fields are '\000', then they are ignored.
private char enclosedBy;
private char escapedBy;
// If true, then the enclosed-by character is applied to every
// field, not just ones containing embedded delimiters.
private boolean encloseRequired;
public static final String OUTPUT_FIELD_DELIM_KEY =
"sqoop.output.field.delim";
public static final String OUTPUT_RECORD_DELIM_KEY =
"sqoop.output.record.delim";
public static final String OUTPUT_ENCLOSED_BY_KEY =
"sqoop.output.enclosed.by";
public static final String OUTPUT_ESCAPED_BY_KEY =
"sqoop.output.escaped.by";
public static final String OUTPUT_ENCLOSE_REQUIRED_KEY =
"sqoop.output.enclose.required";
/**
* Create the input variations for export instead of overloading them.
*/
public static final String INPUT_FIELD_DELIM_KEY =
"sqoop.input.field.delim";
public static final String INPUT_RECORD_DELIM_KEY =
"sqoop.input.record.delim";
public static final String INPUT_ENCLOSED_BY_KEY =
"sqoop.input.enclosed.by";
public static final String INPUT_ESCAPED_BY_KEY =
"sqoop.input.escaped.by";
public static final String INPUT_ENCLOSE_REQUIRED_KEY =
"sqoop.input.enclose.required";
// Static delimiter sets for the commonly-used delimiter arrangements.
public static final DelimiterSet DEFAULT_DELIMITERS;
public static final DelimiterSet HIVE_DELIMITERS;
public static final DelimiterSet MYSQL_DELIMITERS;
static {
DEFAULT_DELIMITERS = new DelimiterSet(',', '\n', NULL_CHAR, NULL_CHAR,
false);
MYSQL_DELIMITERS = new DelimiterSet(',', '\n', '\'', '\\', false);
HIVE_DELIMITERS = new DelimiterSet('\001', '\n',
NULL_CHAR, NULL_CHAR, false);
}
/**
* Create a delimiter set with the default delimiters
* (comma for fields, newline for records).
*/
public DelimiterSet() {
this(',', '\n', NULL_CHAR, NULL_CHAR, false);
}
/**
* Create a delimiter set with the specified delimiters.
* @param field the fields-terminated-by delimiter
* @param record the lines-terminated-by delimiter
* @param enclose the enclosed-by character
* @param escape the escaped-by character
* @param isEncloseRequired If true, enclosed-by is applied to all
* fields. If false, only applied to fields that embed delimiters.
*/
public DelimiterSet(char field, char record, char enclose, char escape,
boolean isEncloseRequired) {
this.fieldDelim = field;
this.recordDelim = record;
this.enclosedBy = enclose;
this.escapedBy = escape;
this.encloseRequired = isEncloseRequired;
}
/**
* Identical to clone() but does not throw spurious exceptions.
* @return a new copy of this same set of delimiters.
*/
public DelimiterSet copy() {
try {
return (DelimiterSet) clone();
} catch (CloneNotSupportedException cnse) {
// Should never happen for DelimiterSet.
return null;
}
}
/**
* Sets the fields-terminated-by character.
*/
public void setFieldsTerminatedBy(char f) {
this.fieldDelim = f;
}
/**
* @return the fields-terminated-by character.
*/
public char getFieldsTerminatedBy() {
return this.fieldDelim;
}
/**
* Sets the end-of-record lines-terminated-by character.
*/
public void setLinesTerminatedBy(char r) {
this.recordDelim = r;
}
/**
* @return the end-of-record (lines-terminated-by) character.
*/
public char getLinesTerminatedBy() {
return this.recordDelim;
}
/**
* Sets the enclosed-by character.
* @param e the enclosed-by character, or '\000' for no enclosing character.
*/
public void setEnclosedBy(char e) {
this.enclosedBy = e;
}
/**
* @return the enclosed-by character, or '\000' for none.
*/
public char getEnclosedBy() {
return this.enclosedBy;
}
/**
* Sets the escaped-by character.
* @param e the escaped-by character, or '\000' for no escape character.
*/
public void setEscapedBy(char e) {
this.escapedBy = e;
}
/**
* @return the escaped-by character, or '\000' for none.
*/
public char getEscapedBy() {
return this.escapedBy;
}
/**
* Set whether the enclosed-by character must be applied to all fields,
* or only fields with embedded delimiters.
*/
public void setEncloseRequired(boolean required) {
this.encloseRequired = required;
}
/**
* @return true if the enclosed-by character must be applied to all fields,
* or false if it's only used for fields with embedded delimiters.
*/
public boolean isEncloseRequired() {
return this.encloseRequired;
}
@Override
/**
* @return a string representation of the delimiters.
*/
public String toString() {
return "fields=" + this.fieldDelim
+ " records=" + this.recordDelim
+ " escape=" + this.escapedBy
+ " enclose=" + this.enclosedBy
+ " required=" + this.encloseRequired;
}
/**
* Format this set of delimiters as a call to the constructor for
* this object, that would generate identical delimiters.
* @return a String that can be embedded in generated code that
* provides this set of delimiters.
*/
public String formatConstructor() {
return "new DelimiterSet((char) " + (int) this.fieldDelim + ", "
+ "(char) " + (int) this.recordDelim + ", "
+ "(char) " + (int) this.enclosedBy + ", "
+ "(char) " + (int) this.escapedBy + ", "
+ this.encloseRequired + ")";
}
@Override
/**
* @return a hash code for this set of delimiters.
*/
public int hashCode() {
return (int) this.fieldDelim
+ (((int) this.recordDelim) << 4)
+ (((int) this.escapedBy) << 8)
+ (((int) this.enclosedBy) << 12)
+ (((int) this.recordDelim) << 16)
+ (this.encloseRequired ? 0xFEFE : 0x7070);
}
@Override
/**
* @return true if this delimiter set is the same as another set of
* delimiters.
*/
public boolean equals(Object other) {
if (null == other) {
return false;
} else if (!other.getClass().equals(getClass())) {
return false;
}
DelimiterSet set = (DelimiterSet) other;
return this.fieldDelim == set.fieldDelim
&& this.recordDelim == set.recordDelim
&& this.escapedBy == set.escapedBy
&& this.enclosedBy == set.enclosedBy
&& this.encloseRequired == set.encloseRequired;
}
@Override
/**
* @return a new copy of this same set of delimiters.
*/
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}