package com.thinkbiganalytics.util;
/*-
* #%L
* thinkbig-nifi-core-processors
* %%
* Copyright (C) 2017 ThinkBig Analytics
* %%
* 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.
* #L%
*/
import com.google.common.io.LineReader;
import com.thinkbiganalytics.hive.util.HiveUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ColumnSpec {
private String name;
private String comment;
private String dataType;
private boolean pk;
private boolean createDt;
private boolean modifiedDt;
public ColumnSpec(String name, String dataType, String comment) {
this(name, dataType, comment, false, false, false);
}
public ColumnSpec(String name, String dataType, String comment, boolean pk, boolean createDt, boolean modifiedDt) {
super();
Validate.notEmpty(name);
this.name = name.toLowerCase().trim();
this.dataType = (StringUtils.isEmpty(dataType) ? "string" : dataType);
this.comment = comment;
this.pk = pk;
this.createDt = createDt;
this.modifiedDt = modifiedDt;
validate();
}
public static String toPrimaryKeyJoinSQL(ColumnSpec[] specs, String leftTableAlias, String rightTableAlias) {
final String safeLeftTable = HiveUtils.quoteIdentifier(leftTableAlias);
final String safeRightTable = HiveUtils.quoteIdentifier(rightTableAlias);
final List<String> keys = Stream.of(specs)
.filter(ColumnSpec::isPk)
.map(ColumnSpec::getName)
.map(HiveUtils::quoteIdentifier)
.map(column -> safeLeftTable + "." + column + " = " + safeRightTable + "." + column)
.collect(Collectors.toList());
return StringUtils.join(keys, " AND ");
}
public static String[] toPrimaryKeys(ColumnSpec[] specs) {
return Stream.of(specs)
.filter(ColumnSpec::isPk)
.map(ColumnSpec::getName)
.map(HiveUtils::quoteIdentifier)
.toArray(String[]::new);
}
/**
* Method for defining a column specification as a pipe-delimited format: column|data type|comment (optional)|pk|created|modified. Each row separated by a newline
*/
public static ColumnSpec[] createFromString(String specString) {
if (StringUtils.isEmpty(specString)) {
return null;
}
List<ColumnSpec> specs = new Vector<>();
try {
LineReader lineReader = new LineReader(
new StringReader(specString));
String line;
while ((line = lineReader.readLine()) != null) {
String[] parts = line.split("\\|");
int len = parts.length;
if (len > 0) {
String columnName = "";
String comment = "";
String dataType = "string";
boolean pk = false;
boolean modifiedDt = false;
boolean createDt = false;
switch (len) {
default:
case 6:
modifiedDt = "1".equals(parts[5].trim());
case 5:
createDt = "1".equals(parts[4].trim());
case 4:
pk = "1".equals(parts[3].trim());
case 3:
comment = parts[2];
case 2:
dataType = parts[1];
case 1:
columnName = parts[0];
}
specs.add(new ColumnSpec(columnName, dataType, comment, pk, createDt, modifiedDt));
}
}
return specs.toArray(new ColumnSpec[0]);
} catch (IOException e) {
throw new RuntimeException("Failed to parse column specs[" + specString + "]", e);
}
}
public void validate() {
Validate.notEmpty(name);
Validate.notEmpty(dataType);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public boolean isPk() {
return pk;
}
public void setPk(boolean pk) {
this.pk = pk;
}
public boolean isCreateDt() {
return createDt;
}
public void setCreateDt(boolean createDt) {
this.createDt = createDt;
}
public boolean isModifiedDt() {
return modifiedDt;
}
public void setModifiedDt(boolean modifiedDt) {
this.modifiedDt = modifiedDt;
}
public String toCreateSQL() {
return toCreateSQL(false);
}
public String toCreateSQL(boolean strings) {
StringBuffer sb = new StringBuffer();
sb.append(HiveUtils.quoteIdentifier(name)).append(' ');
sb.append((strings ? "string" : dataType));
if (!StringUtils.isEmpty(comment)) {
sb.append(" COMMENT ").append(HiveUtils.quoteString(comment));
}
return sb.toString();
}
public String toPartitionSQL() {
return HiveUtils.quoteIdentifier(name) + " " + dataType;
}
}