/**
* 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.flowlog;
import java.io.File;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.TreeMap;
import com.asakusafw.yaess.core.ExecutionContext;
import com.asakusafw.yaess.core.ServiceProfile;
/**
* A structured profile for {@link FlowLoggerProvider}.
* @since 0.2.6
*/
public class FlowLoggerProfile {
static final String KEY_DIRECTORY = "directory";
static final String KEY_ENCODING = "encoding";
static final String KEY_STEP_UNIT = "stepUnit";
static final String KEY_DATE_FORMAT = "dateFormat";
static final String KEY_REPORT_JOB = "reportJob";
static final String KEY_DELETE_ON_SETUP = "deleteOnSetup";
static final String KEY_DELETE_ON_CLEANUP = "deleteOnCleanup";
static final String DEFAULT_ENCODING = "UTF-8";
static final String DEFAULT_STEP_UNIT = "0.00";
static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
static final String DEFAULT_REPORT_JOB = "true";
static final String DEFAULT_DELETE_ON_SETUP = "true";
static final String DEFAULT_DELETE_ON_CLEANUP = "true";
private final File directory;
private final Charset encoding;
private final DateFormat dateFormat;
private final double stepUnit;
private final boolean reportJob;
private final boolean deleteOnSetup;
private final boolean deleteOnCleanup;
FlowLoggerProfile(
File directory,
Charset encoding,
DateFormat dateFormat,
double stepUnit,
boolean reportJob,
boolean deleteOnSetup,
boolean deleteOnCleanup) {
if (directory == null) {
throw new IllegalArgumentException("directory must not be null"); //$NON-NLS-1$
}
if (encoding == null) {
throw new IllegalArgumentException("encoding must not be null"); //$NON-NLS-1$
}
if (dateFormat == null) {
throw new IllegalArgumentException("dateFormat must not be null"); //$NON-NLS-1$
}
this.directory = directory;
this.encoding = encoding;
this.dateFormat = dateFormat;
this.stepUnit = stepUnit;
this.reportJob = reportJob;
this.deleteOnSetup = deleteOnSetup;
this.deleteOnCleanup = deleteOnCleanup;
}
/**
* Returns the base directory of log output target.
* @return the output base directory
*/
public File getDirectory() {
return directory;
}
/**
* Returns the log output encoding.
* @return the log output encoding
*/
public Charset getEncoding() {
return encoding;
}
/**
* Returns the log date format.
* @return the log date format
*/
public DateFormat getDateFormat() {
return (DateFormat) dateFormat.clone();
}
/**
* Returns the step unit.
* @return the step unit
*/
public double getStepUnit() {
return stepUnit;
}
/**
* Returns whether report job status.
* @return {@code true} to report job status, otherwise {@code false}
*/
public boolean isReportJob() {
return reportJob;
}
/**
* Returns whether delete logs before cleanup phase was started.
* @return {@code true} to delete logs, otherwise {@code false}
* @throws IllegalArgumentException if some parameters were {@code null}
*/
public boolean isDeleteOnSetup() {
return deleteOnSetup;
}
/**
* Returns whether delete logs after cleanup phase was succeeded.
* @return {@code true} to delete logs, otherwise {@code false}
* @throws IllegalArgumentException if some parameters were {@code null}
*/
public boolean isDeleteOnCleanup() {
return deleteOnCleanup;
}
/**
* Returns abstract path for the target log file.
* @param context current context
* @return target log file
* @throws IllegalArgumentException if some parameters were {@code null}
*/
public File getLogFile(ExecutionContext context) {
if (context == null) {
throw new IllegalArgumentException("context must not be null"); //$NON-NLS-1$
}
return getFile(context, "logs");
}
/**
* Returns abstract path for the escaped log file.
* @param context current context
* @return escaped log file
* @throws IllegalArgumentException if some parameters were {@code null}
*/
public File getEscapeFile(ExecutionContext context) {
if (context == null) {
throw new IllegalArgumentException("context must not be null"); //$NON-NLS-1$
}
return getFile(context, "cleanup");
}
private File getFile(ExecutionContext context, String dirName) {
assert context != null;
assert dirName != null;
File base = new File(getDirectory(), context.getBatchId());
File ongoing = new File(base, dirName);
File log = new File(ongoing, context.getFlowId());
return log;
}
/**
* Converts the generic profile into the structured profile about {@link FlowLogger}.
* @param profile the target profile
* @return the converted profile
* @throws IllegalArgumentException if some parameters were invalid
*/
public static FlowLoggerProfile convert(ServiceProfile<?> profile) {
if (profile == null) {
throw new IllegalArgumentException("profile must not be null"); //$NON-NLS-1$
}
Map<String, String> copy = new TreeMap<>(profile.getConfiguration());
String dirString = extract(profile, copy, KEY_DIRECTORY, null);
String encString = extract(profile, copy, KEY_ENCODING, DEFAULT_ENCODING);
String dfString = extract(profile, copy, KEY_DATE_FORMAT, DEFAULT_DATE_FORMAT);
double stepUnit = extractDouble(profile, copy, KEY_STEP_UNIT, DEFAULT_STEP_UNIT);
boolean reportJob = extractBoolean(profile, copy, KEY_REPORT_JOB, DEFAULT_REPORT_JOB);
boolean deleteOnSetup = extractBoolean(profile, copy, KEY_DELETE_ON_SETUP, DEFAULT_DELETE_ON_SETUP);
boolean deleteOnCleanup = extractBoolean(profile, copy, KEY_DELETE_ON_CLEANUP, DEFAULT_DELETE_ON_CLEANUP);
if (copy.isEmpty() == false) {
throw new IllegalArgumentException(MessageFormat.format(
"Unknown profile parameters in {0} ({1})",
profile.getPrefix(),
copy));
}
File file = new File(dirString);
Charset encoding;
try {
encoding = Charset.forName(encString);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(MessageFormat.format(
"Invalid charset in {0}.{1} ({2})",
profile.getPrefix(),
KEY_ENCODING,
encString), e);
}
DateFormat dateFormat;
try {
dateFormat = new SimpleDateFormat(dfString);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(MessageFormat.format(
"Invalid date format in {0}.{1} ({2})",
profile.getPrefix(),
KEY_DATE_FORMAT,
dfString), e);
}
return new FlowLoggerProfile(
file, encoding, dateFormat,
stepUnit,
reportJob,
deleteOnSetup, deleteOnCleanup);
}
private static String extract(
ServiceProfile<?> profile,
Map<String, String> copy,
String key,
String defaultValue) {
String value = profile.normalize(key, copy.remove(key), defaultValue == null, true);
if (value == null) {
assert defaultValue != null;
return defaultValue;
}
return value;
}
private static double extractDouble(
ServiceProfile<?> profile,
Map<String, String> copy,
String key,
String defaultValue) {
String value = extract(profile, copy, key, defaultValue);
try {
return Double.parseDouble(value);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(MessageFormat.format(
"{0}.{1} must be a floating point number ({2})",
profile.getPrefix(),
key,
value), e);
}
}
private static boolean extractBoolean(
ServiceProfile<?> profile,
Map<String, String> copy,
String key,
String defaultValue) {
String value = extract(profile, copy, key, defaultValue);
if (value.equalsIgnoreCase("true")) {
return true;
} else if (value.equals("false")) {
return false;
} else {
throw new IllegalArgumentException(MessageFormat.format(
"{0}.{1} must be a boolean value ({2})",
profile.getPrefix(),
key,
value));
}
}
}