| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * 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 vogar; |
| |
| import com.google.gson.stream.JsonReader; |
| import com.google.gson.stream.JsonWriter; |
| import java.io.File; |
| import java.io.FileReader; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.text.SimpleDateFormat; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Date; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import java.util.TimeZone; |
| import vogar.commands.Mkdir; |
| import vogar.commands.Rm; |
| |
| public final class OutcomeStore { |
| private static final String FILE_NAME_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssz"; |
| private static final int PRESERVE_TOTAL = 10; |
| |
| private static final Comparator<File> ORDER_BY_LAST_MODIFIED = new Comparator<File>() { |
| @Override public int compare(File a, File b) { |
| if (a.lastModified() != b.lastModified()) { |
| return a.lastModified() < b.lastModified() ? -1 : 1; |
| } |
| return 0; |
| } |
| }; |
| |
| private final Log log; |
| private final Mkdir mkdir; |
| private final Rm rm; |
| private final File resultsDir; |
| private final boolean recordResults; |
| private final ExpectationStore expectationStore; |
| private final Date date; |
| |
| public OutcomeStore(Log log, Mkdir mkdir, Rm rm, File resultsDir, boolean recordResults, |
| ExpectationStore expectationStore, Date date) { |
| this.log = log; |
| this.mkdir = mkdir; |
| this.rm = rm; |
| this.resultsDir = resultsDir; |
| this.recordResults = recordResults; |
| this.expectationStore = expectationStore; |
| this.date = date; |
| } |
| |
| public Map<String, AnnotatedOutcome> read(Map<String, Outcome> outcomes) { |
| Map<String, AnnotatedOutcome> result = new LinkedHashMap<String, AnnotatedOutcome>(); |
| for (Map.Entry<String, Outcome> entry : outcomes.entrySet()) { |
| Outcome outcome = entry.getValue(); |
| Expectation expectation = expectationStore.get(outcome); |
| result.put(entry.getKey(), new AnnotatedOutcome(outcome, expectation)); |
| } |
| |
| try { |
| File[] oldOutcomes = getOutcomeFiles(); |
| log.verbose("parsing outcomes from " + oldOutcomes.length + " files"); |
| for (File file : oldOutcomes) { |
| if (!file.getName().endsWith(".json")) { |
| continue; |
| } |
| |
| loadOutcomes(result, file, file.lastModified()); |
| } |
| } catch (IOException e) { |
| log.info("Failed to read outcomes from " + resultsDir, e); |
| } |
| |
| return result; |
| } |
| |
| private void loadOutcomes(Map<String, AnnotatedOutcome> map, File file, long fileDate) |
| throws IOException { |
| JsonReader in = new JsonReader(new FileReader(file)); |
| in.beginObject(); |
| while (in.hasNext()) { |
| String outcomeName = in.nextName(); |
| AnnotatedOutcome annotatedOutcome = map.get(outcomeName); |
| if (annotatedOutcome == null) { |
| in.skipValue(); |
| continue; |
| } |
| |
| Result result = null; |
| in.beginObject(); |
| while (in.hasNext()) { |
| String fieldName = in.nextName(); |
| if (fieldName.equals("result")) { |
| result = Result.valueOf(in.nextString()); |
| } else { |
| in.skipValue(); |
| } |
| } |
| in.endObject(); |
| |
| annotatedOutcome.add(fileDate, new Outcome(outcomeName, result, |
| Collections.<String>emptyList())); |
| } |
| in.endObject(); |
| in.close(); |
| } |
| |
| public void write(Map<String, Outcome> outcomes) { |
| if (!recordResults) { |
| return; |
| } |
| |
| makeRoom(); |
| File outputFile = getOutputFile(); |
| try { |
| mkdir.mkdirs(outputFile.getParentFile()); |
| JsonWriter out = new JsonWriter(new FileWriter(outputFile)); |
| out.setIndent(" "); |
| out.beginObject(); |
| for (Map.Entry<String, Outcome> entry : outcomes.entrySet()) { |
| out.name(entry.getKey()); |
| out.beginObject(); |
| out.name("result"); |
| out.value(entry.getValue().getResult().toString()); |
| out.endObject(); |
| } |
| out.endObject(); |
| out.close(); |
| } catch (IOException e) { |
| log.info("Failed to write outcomes to " + outputFile, e); |
| } |
| } |
| |
| private File[] getOutcomeFiles() { |
| File[] result = resultsDir.listFiles(); |
| if (result == null) { |
| return new File[0]; |
| } |
| Arrays.sort(result, ORDER_BY_LAST_MODIFIED); |
| return result; |
| } |
| |
| private File getOutputFile() { |
| SimpleDateFormat dateFormat = new SimpleDateFormat(FILE_NAME_DATE_FORMAT); |
| dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); |
| dateFormat.setLenient(true); |
| String timestamp = dateFormat.format(date); |
| return new File(resultsDir, timestamp + ".json"); |
| } |
| |
| /** |
| * Removes the oldest result files until only (PRESERVE_TOTAL - 1) remain. |
| */ |
| private void makeRoom() { |
| File[] outcomeFiles = getOutcomeFiles(); |
| for (int i = 0; i <= (outcomeFiles.length - PRESERVE_TOTAL); i++) { |
| rm.file(outcomeFiles[i]); |
| log.verbose("garbage collected results file: " + outcomeFiles[i]); |
| } |
| } |
| } |