package crate.elasticsearch.action.dump.parser;
import crate.elasticsearch.action.export.ExportContext;
import crate.elasticsearch.action.export.parser.ExportForceOverwriteParseElement;
import crate.elasticsearch.action.export.parser.IExportParser;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.SearchParseElement;
import org.elasticsearch.search.SearchParseException;
import org.elasticsearch.search.fetch.FetchPhase;
import org.elasticsearch.search.query.QueryPhase;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* Dump specific parser class
*/
public class DumpParser implements IExportParser {
public static final String[] DEFAULT_FIELDS = {"_id", "_source", "_timestamp", "_ttl", "_version", "_index",
"_type", "_routing"};
public static final String FILENAME_PATTERN = "${cluster}_${index}_${shard}.json.gz";
public static final String DEFAULT_DIR = "dump";
private final ImmutableMap<String, SearchParseElement> elementParsers;
private final DumpDirectoryParseElement directoryParseElement = new DumpDirectoryParseElement();
@Inject
public DumpParser(QueryPhase queryPhase, FetchPhase fetchPhase) {
Map<String, SearchParseElement> elementParsers = new HashMap<String, SearchParseElement>();
elementParsers.putAll(queryPhase.parseElements());
elementParsers.put("force_overwrite", new ExportForceOverwriteParseElement());
elementParsers.put("directory", directoryParseElement);
this.elementParsers = ImmutableMap.copyOf(elementParsers);
}
/**
* Main method of this class to parse given payload of _dump action
*
* @param context
* @param source
* @throws SearchParseException
*/
public void parseSource(ExportContext context, BytesReference source) throws SearchParseException {
XContentParser parser = null;
this.setDefaults(context);
try {
if (source != null && source.length() != 0) {
parser = XContentFactory.xContent(source).createParser(source);
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
String fieldName = parser.currentName();
parser.nextToken();
SearchParseElement element = elementParsers.get(fieldName);
if (element == null) {
throw new SearchParseException(context, "No parser for element [" + fieldName + "]");
}
element.parse(parser, context);
} else if (token == null) {
break;
}
}
}
if (context.outputFile() == null) {
directoryParseElement.setOutPutFile(context, DEFAULT_DIR);
this.ensureDefaultDirectory(context);
}
context.mappings(true);
context.settings(true);
} catch (Exception e) {
String sSource = "_na_";
try {
sSource = XContentHelper.convertToJson(source, false);
} catch (Throwable e1) {
// ignore
}
throw new SearchParseException(context, "Failed to parse source [" + sSource + "]", e);
} finally {
if (parser != null) {
parser.close();
}
}
}
/**
* Set dump specific default values to the context like directory, compression or fields to export
*
* @param context
*/
private void setDefaults(ExportContext context) {
context.compression(true);
for (int i = 0; i < DEFAULT_FIELDS.length; i++) {
context.fieldNames().add(DEFAULT_FIELDS[i]);
}
}
/**
* create default dump directory if it does not exist
*
* @param context
*/
private void ensureDefaultDirectory(ExportContext context) {
File dumpFile = new File(context.outputFile());
File dumpDir = new File(dumpFile.getParent());
if (!dumpDir.exists()) {
dumpDir.mkdir();
}
}
}