/**
* 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.yaess.iterative;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.asakusafw.iterative.common.IterativeExtensions;
import com.asakusafw.iterative.common.ParameterTable;
import com.asakusafw.yaess.basic.BasicExtension;
import com.asakusafw.yaess.core.Extension;
import com.asakusafw.yaess.core.ExtensionHandler;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
/**
* Handles {@link ParameterTable}.
* @since 0.8.0
*/
public class ParameterTableHandler implements ExtensionHandler {
static final Logger LOG = LoggerFactory.getLogger(ParameterTableHandler.class);
/**
* The extension tag name.
*/
public static final String TAG = "parameter-table";
@Override
public Extension handle(String tag, String value) throws IOException {
if (tag.equals(TAG) == false) {
return null;
}
File file = new File(value);
if (file.isFile() == false) {
throw new FileNotFoundException(file.getAbsolutePath());
}
ParameterTable table = parse(file);
File temporary = File.createTempFile("asakusa-iterative-", ".bin"); //$NON-NLS-1$ //$NON-NLS-2$
boolean success = false;
try (OutputStream output = new FileOutputStream(temporary)) {
LOG.debug("storing parameter table: {}", temporary); //$NON-NLS-1$
IterativeExtensions.save(output, table);
success = true;
} finally {
if (success == false) {
if (temporary.delete() == false && temporary.exists()) {
LOG.warn(MessageFormat.format(
"failed to delete temporary file: {0}", //$NON-NLS-1$
temporary));
}
}
}
return new BasicExtension(IterativeExtensions.EXTENSION_NAME, temporary, true);
}
static ParameterTable parse(File file) throws IOException {
LOG.debug("parsing JSON parameter table: {}", file); //$NON-NLS-1$
JsonFactory json = new JsonFactory();
json.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
json.enable(JsonParser.Feature.ALLOW_COMMENTS);
json.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
json.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
json.enable(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER);
json.enable(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS);
try (JsonParser parser = json.createParser(file)) {
ParameterTable.Builder builder = IterativeExtensions.builder();
while (true) {
JsonToken t = parser.nextToken();
if (t == null) {
break;
} else if (t == JsonToken.START_OBJECT) {
builder.next();
parseRow(parser, builder);
} else {
throw new IOException(MessageFormat.format(
"invalid JSON format (invalid start object): {0}",
parser.getCurrentLocation()));
}
}
return builder.build();
}
}
private static void parseRow(JsonParser parser, ParameterTable.Builder builder) throws IOException {
while (true) {
JsonToken t0 = parser.nextToken();
if (t0 == JsonToken.END_OBJECT) {
return;
} else if (t0 != JsonToken.FIELD_NAME) {
throw new IOException(MessageFormat.format(
"invalid JSON format (invalid field name): {0}",
parser.getCurrentLocation()));
}
String name = parser.getCurrentName();
JsonToken t1 = parser.nextToken();
if (t1 == null) {
throw new IOException(MessageFormat.format(
"invalid JSON format (unexpected EOF): {0}",
parser.getCurrentLocation()));
}
switch (t1) {
case VALUE_STRING:
case VALUE_NUMBER_FLOAT:
case VALUE_NUMBER_INT:
case VALUE_TRUE:
case VALUE_FALSE:
// ok
break;
default:
throw new IOException(MessageFormat.format(
"invalid JSON format (unsupported value): {0}",
parser.getCurrentLocation()));
}
String value = parser.getValueAsString();
builder.put(name, value);
}
}
}