/*
* Copyright 2014 the original author or authors.
*
* 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 org.springframework.xd.hadoop.fs;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.kitesdk.data.PartitionStrategy;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.hadoop.store.StoreException;
import org.springframework.data.hadoop.store.dataset.DatasetDefinition;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.expression.spel.SpelParseException;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.StringUtils;
/**
* FactoryBean that creates a default DatasetDefinition
*
* @author Thomas Risberg
*/
public class DatasetDefinitionFactoryBean implements InitializingBean, FactoryBean<DatasetDefinition> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private String format;
private Boolean allowNullValues;
private String partitionPath;
private int writerCacheSize;
private String compressionType;
private DatasetDefinition datasetDefinition;
public void setFormat(String format) {
this.format = format;
}
public void setAllowNullValues(Boolean allowNullValues) {
this.allowNullValues = allowNullValues;
}
public void setPartitionPath(String partitionPath) {
this.partitionPath = partitionPath;
}
public void setWriterCacheSize(int writerCacheSize) {
this.writerCacheSize = writerCacheSize;
}
public void setCompressionType(String compressionType) {
this.compressionType = compressionType;
}
@Override
public DatasetDefinition getObject() throws Exception {
return datasetDefinition;
}
@Override
public Class<?> getObjectType() {
return DatasetDefinition.class;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void afterPropertiesSet() throws Exception {
logger.info("DatasetDefinition properties: ");
logger.info(" allowNulValues: " + allowNullValues);
logger.info(" format: " + format);
logger.info(" partitionPath: " + partitionPath);
logger.info(" writerCacheSize: " + writerCacheSize);
logger.info(" compressionType: " + compressionType);
datasetDefinition = new DatasetDefinition(allowNullValues, format);
if (StringUtils.hasText(partitionPath)) {
datasetDefinition.setPartitionStrategy(parsePartitionExpression(partitionPath));
}
if (writerCacheSize > 0) {
datasetDefinition.setWriterCacheSize(writerCacheSize);
}
if (StringUtils.hasText(compressionType)) {
datasetDefinition.setCompressionType(compressionType);
}
}
private static PartitionStrategy parsePartitionExpression(String expression) {
List<String> expressions = Arrays.asList(expression.split("/"));
ExpressionParser parser = new SpelExpressionParser();
PartitionStrategy.Builder psb = new PartitionStrategy.Builder();
StandardEvaluationContext ctx = new StandardEvaluationContext(psb);
for (String expr : expressions) {
try {
Expression e = parser.parseExpression(expr);
psb = e.getValue(ctx, PartitionStrategy.Builder.class);
}
catch (SpelParseException spe) {
if (!expr.trim().endsWith(")")) {
throw new StoreException("Invalid partitioning expression '" + expr
+ "' - did you forget the closing parenthesis?", spe);
}
else {
throw new StoreException("Invalid partitioning expression '" + expr + "'!", spe);
}
}
catch (SpelEvaluationException see) {
throw new StoreException("Invalid partitioning expression '" + expr + "' - failed evaluation!", see);
}
catch (NullPointerException npe) {
throw new StoreException("Invalid partitioning expression '" + expr + "' - was evaluated to null!", npe);
}
}
return psb.build();
}
}