// Copyright 2013 Michel Kraemer
//
// 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 de.undercouch.citeproc;
import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Map;
import de.undercouch.citeproc.csl.CSLDate;
import de.undercouch.citeproc.csl.CSLDateBuilder;
import de.undercouch.citeproc.script.ScriptRunner;
import de.undercouch.citeproc.script.ScriptRunnerException;
import de.undercouch.citeproc.script.ScriptRunnerFactory;
/**
* An intelligent parser for date strings. This class is able to handle
* a wide range of date formats (e.g. YYYY-mm-dd, YYYY/mm/dd, Month YYYY)
* @author Michel Kraemer
*/
public class CSLDateParser {
/**
* A JavaScript runner used to execute citeproc-js
*/
private final ScriptRunner runner;
/**
* The underlying date parser
*/
private final Object parser;
/**
* Creates a new date parser
*/
public CSLDateParser() {
//create JavaScript runner
runner = ScriptRunnerFactory.createRunner();
//load bundles scripts
try {
runner.eval(new StringReader(
"var CSL = new function() {};" +
"CSL.DATE_PARTS_ALL = [\"year\", \"month\", \"day\", \"season\"];" +
"CSL.debug = function(msg) {};" +
"function getParser() { return CSL.DateParser; }"
));
runner.loadScript(getClass().getResource("dateparser.js"));
} catch (IOException e) {
//should never happen because bundled JavaScript files should be readable indeed
} catch (ScriptRunnerException e) {
//should never happen because bundled JavaScript files should be OK indeed
throw new RuntimeException("Invalid bundled javascript file", e);
}
//initialize parser
try {
parser = runner.callMethod("getParser", Object.class);
} catch (ScriptRunnerException e) {
throw new IllegalArgumentException("Could not initialize date parser", e);
}
}
/**
* Parses a string to a date
* @param str the string to parse
* @return the parsed date
*/
public CSLDate parse(String str) {
Map<String, Object> res;
try {
Map<String, Object> m = runner.callMethod(
parser, "parseDateToArray", Map.class, str);
res = m;
} catch (ScriptRunnerException e) {
throw new IllegalArgumentException("Could not update items", e);
}
CSLDate r = CSLDate.fromJson(res);
if (r.getDateParts().length == 2 && Arrays.equals(r.getDateParts()[0], r.getDateParts()[1])) {
r = new CSLDateBuilder(r).dateParts(r.getDateParts()[0]).build();
}
return r;
}
}