/* * Copyright (C) 2013-2015 Daniel Dietsch (dietsch@informatik.uni-freiburg.de) * Copyright (C) 2008-2015 Jochen Hoenicke (hoenicke@informatik.uni-freiburg.de) * Copyright (C) 2015 University of Freiburg * * This file is part of the ULTIMATE BoogiePrinter plug-in. * * The ULTIMATE BoogiePrinter plug-in is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ULTIMATE BoogiePrinter plug-in is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ULTIMATE BoogiePrinter plug-in. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE BoogiePrinter plug-in, or any covered work, by linking * or combining it with Eclipse RCP (or a modified version of Eclipse RCP), * containing parts covered by the terms of the Eclipse Public License, the * licensors of the ULTIMATE BoogiePrinter plug-in grant you additional permission * to convey the resulting work. */ /** * Boogie printer observer. */ package de.uni_freiburg.informatik.ultimate.req.printer; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import de.uni_freiburg.informatik.ultimate.boogie.ast.Unit; import de.uni_freiburg.informatik.ultimate.core.lib.models.ObjectContainer; import de.uni_freiburg.informatik.ultimate.core.model.models.IElement; import de.uni_freiburg.informatik.ultimate.core.model.models.ILocation; import de.uni_freiburg.informatik.ultimate.core.model.models.ModelType; import de.uni_freiburg.informatik.ultimate.core.model.observers.IUnmanagedObserver; import de.uni_freiburg.informatik.ultimate.core.model.services.ILogger; import de.uni_freiburg.informatik.ultimate.core.model.services.IUltimateServiceProvider; import de.uni_freiburg.informatik.ultimate.lib.srparse.pattern.DeclarationPattern; import de.uni_freiburg.informatik.ultimate.lib.srparse.pattern.DeclarationPattern.VariableCategory; import de.uni_freiburg.informatik.ultimate.lib.srparse.pattern.PatternType; import de.uni_freiburg.informatik.ultimate.pea2boogie.PatternContainer; import de.uni_freiburg.informatik.ultimate.req.printer.preferences.PreferenceInitializer; /** * @author hoenicke */ public class ReqPrinterObserver implements IUnmanagedObserver { private final ILogger mLogger; private final IUltimateServiceProvider mServices; public ReqPrinterObserver(final IUltimateServiceProvider services) { mServices = services; mLogger = services.getLoggingService().getLogger(Activator.PLUGIN_ID); } @Override public boolean process(final IElement root) { if (root instanceof Unit) { final PatternContainer container = PatternContainer.getAnnotation(root); if (container == null) { mLogger.warn("No requirements found"); return false; } final List pattern = new ArrayList<>(container.getPatterns()); printPatternList(root, pattern); return false; } else if (root instanceof ObjectContainer) { if (((ObjectContainer) root).getValue() instanceof List) { final List pattern = (List) ((ObjectContainer) root).getValue(); printPatternList(root, pattern); } return false; } return true; } private void printPatternList(final IElement root, final List sortedPatterns) { final PrintWriter writer = openTempFile(root); sortedPatterns.sort(new Comparator() { @Override public int compare(final PatternType o1, final PatternType o2) { if (o1 instanceof DeclarationPattern) { if (o2 instanceof DeclarationPattern) { final VariableCategory o1cat = ((DeclarationPattern) o1).getCategory(); final VariableCategory o2cat = ((DeclarationPattern) o2).getCategory(); if (o1cat == VariableCategory.CONST && o2cat != VariableCategory.CONST) { return -1; } else if (o2cat == VariableCategory.CONST && o1cat != VariableCategory.CONST) { return 1; } } else { return -1; } } else if (o2 instanceof DeclarationPattern) { return 1; } return o1.getId().compareToIgnoreCase(o2.getId()); } }); for (final PatternType pattern : sortedPatterns) { writer.println(pattern.toString()); } writer.close(); } private PrintWriter openTempFile(final IElement root) { final String path = getPath(root); try { final File file; if (mServices.getPreferenceProvider(Activator.PLUGIN_ID) .getBoolean(PreferenceInitializer.UNIQUE_NAME_LABEL)) { file = File.createTempFile( ReqPrinter.class.getSimpleName() + "_" + new File(ILocation.getAnnotation(root).getFileName()).getName() + "_UID", ".req", new File(path)); } else { final String filename = mServices.getPreferenceProvider(Activator.PLUGIN_ID) .getString(PreferenceInitializer.FILE_NAME_LABEL); file = new File(path + File.separatorChar + filename); if ((!file.isFile() || !file.canWrite()) && file.exists()) { mLogger.warn("Cannot write to: " + file.getAbsolutePath()); return null; } if (file.exists()) { mLogger.info("File already exists and will be overwritten: " + file.getAbsolutePath()); } file.createNewFile(); } mLogger.info("Writing to file " + file.getAbsolutePath()); return new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))), false); } catch (final IOException e) { mLogger.fatal("Cannot open file", e); return null; } } private String getPath(final IElement root) { if (mServices.getPreferenceProvider(Activator.PLUGIN_ID) .getBoolean(PreferenceInitializer.SAVE_IN_SOURCE_DIRECTORY_LABEL)) { final ILocation loc = ILocation.getAnnotation(root); final File inputFile = new File(loc.getFileName()); final String path; if (inputFile.isDirectory()) { path = inputFile.getPath(); } else { path = inputFile.getParent(); } if (path != null) { return path; } mLogger.warn("Model does not provide a valid source location, falling back to default dump path..."); } return mServices.getPreferenceProvider(Activator.PLUGIN_ID).getString(PreferenceInitializer.DUMP_PATH_LABEL); } @Override public void finish() { // not required } @Override public void init(final ModelType modelType, final int currentModelIndex, final int numberOfModels) { // not required } @Override public boolean performedChanges() { return false; } }