/******************************************************************************* * CogTool Copyright Notice and Distribution Terms * CogTool 1.3, Copyright (c) 2005-2013 Carnegie Mellon University * This software is distributed under the terms of the FSF Lesser * Gnu Public License (see LGPL.txt). * * CogTool 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 2.1 of the License, or * (at your option) any later version. * * CogTool 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 CogTool; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * CogTool makes use of several third-party components, with the * following notices: * * Eclipse SWT version 3.448 * Eclipse GEF Draw2D version 3.2.1 * * Unless otherwise indicated, all Content made available by the Eclipse * Foundation is provided to you under the terms and conditions of the Eclipse * Public License Version 1.0 ("EPL"). A copy of the EPL is provided with this * Content and is also available at http://www.eclipse.org/legal/epl-v10.html. * * CLISP version 2.38 * * Copyright (c) Sam Steingold, Bruno Haible 2001-2006 * This software is distributed under the terms of the FSF Gnu Public License. * See COPYRIGHT file in clisp installation folder for more information. * * ACT-R 6.0 * * Copyright (c) 1998-2007 Dan Bothell, Mike Byrne, Christian Lebiere & * John R Anderson. * This software is distributed under the terms of the FSF Lesser * Gnu Public License (see LGPL.txt). * * Apache Jakarta Commons-Lang 2.1 * * This product contains software developed by the Apache Software Foundation * (http://www.apache.org/) * * jopt-simple version 1.0 * * Copyright (c) 2004-2013 Paul R. Holser, Jr. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Mozilla XULRunner 1.9.0.5 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/. * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The J2SE(TM) Java Runtime Environment version 5.0 * * Copyright 2009 Sun Microsystems, Inc., 4150 * Network Circle, Santa Clara, California 95054, U.S.A. All * rights reserved. U.S. * See the LICENSE file in the jre folder for more information. ******************************************************************************/ package edu.cmu.cs.hcii.cogtool.controller; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import edu.cmu.cs.hcii.cogtool.model.CachedGoogleSimilarity; import edu.cmu.cs.hcii.cogtool.model.CachedTermSimilarity; import edu.cmu.cs.hcii.cogtool.model.Design; import edu.cmu.cs.hcii.cogtool.model.GLSASimilarity; import edu.cmu.cs.hcii.cogtool.model.GoogleSimilarity; import edu.cmu.cs.hcii.cogtool.model.ISimilarityDictionary; import edu.cmu.cs.hcii.cogtool.model.ISitedTermSimilarity; import edu.cmu.cs.hcii.cogtool.model.ITermSimilarity; import edu.cmu.cs.hcii.cogtool.model.LSASimilarity; import edu.cmu.cs.hcii.cogtool.model.GensimLSASimilarity; import edu.cmu.cs.hcii.cogtool.model.MSRSimilarity; import edu.cmu.cs.hcii.cogtool.model.WidgetAttributes; import edu.cmu.cs.hcii.cogtool.model.ISimilarityDictionary.DictEntry; import edu.cmu.cs.hcii.cogtool.model.ISimilarityDictionary.DictValue; import edu.cmu.cs.hcii.cogtool.ui.Interaction; import edu.cmu.cs.hcii.cogtool.ui.ProjectLID; import edu.cmu.cs.hcii.cogtool.util.AUndoableEdit; import edu.cmu.cs.hcii.cogtool.util.CSVSupport; import edu.cmu.cs.hcii.cogtool.util.FileUtil; import edu.cmu.cs.hcii.cogtool.util.IUndoableEditSequence; import edu.cmu.cs.hcii.cogtool.util.L10N; import edu.cmu.cs.hcii.cogtool.util.NullSafe; import edu.cmu.cs.hcii.cogtool.util.PersistentDate; import edu.cmu.cs.hcii.cogtool.util.RcvrParsingException; public class DictionaryEditorCmd { protected static final String DEFAULT_DICT_PREFIX = L10N.get("PM.NewDictName", "Dictionary"); protected static int nextNewDictSuffix = 1; protected static final String IMPORT_DICTIONARY = L10N.get("PC.ImportDictionary", "Import Dictionary"); protected static final String DICT_CSV_VERSION_0 = "0"; protected static String getAlgorithmName(ITermSimilarity algorithm) { String result = "Manual"; if (GLSASimilarity.ONLY.equals(algorithm)) { result = "GLSA"; } else if (MSRSimilarity.ONLY.equals(algorithm)) { result = "MSR"; } else if (algorithm instanceof LSASimilarity) { result = "LSA"; } else if (algorithm instanceof GensimLSASimilarity) { result = "GENSIM"; } else if (algorithm instanceof CachedGoogleSimilarity) { result = "Old Google"; } else if (algorithm instanceof GoogleSimilarity) { result = "Google"; } return result; } protected static ITermSimilarity getNameAlgorithm(String name, String site, String space) { ITermSimilarity result = ITermSimilarity.MANUAL; if ("GLSA".equals(name)) { result = GLSASimilarity.ONLY; } else if ("MSR".equals(name)) { result = MSRSimilarity.ONLY; } else if ("LSA".equals(name)) { result = LSASimilarity.create(space, site); } else if ("GENSIM".equals(name)) { result = GensimLSASimilarity.create(site); } else if ("Old Google".equals(name)) { result = CachedGoogleSimilarity.create(site); } else if ("Google".equals(name)) { result = GoogleSimilarity.create(site); } return result; } protected static String toString(double similarity) { return CachedTermSimilarity.toString(similarity); } public static boolean exportDictionaryToCSV(ISimilarityDictionary dictionary, Interaction interaction) { File dest = interaction.selectCSVFileDest(DEFAULT_DICT_PREFIX + "" + nextNewDictSuffix++); if (dest == null) { return false; } if (dictionary.size() == 0) { interaction.reportProblem("Export Dictionary", "Selected dictionary is empty"); return true; } FileWriter fw = null; BufferedWriter buffer = null; try { fw = new FileWriter(dest); buffer = new BufferedWriter(fw); // first write out header, version, and column titles CSVSupport.writeCell(ISimilarityDictionary.COGTOOL_DICT_HEADER, buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell(DICT_CSV_VERSION_0, buffer); CSVSupport.addLineEnding(buffer); CSVSupport.writeCell("Term", buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell("Display Labels", buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell("Algorithm", buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell("Limiting URL", buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell("Similarity", buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell("Date computed", buffer); CSVSupport.addLineEnding(buffer); Iterator<DictEntry> values = dictionary.getEntries().iterator(); while (values.hasNext()) { DictEntry entry = values.next(); DictValue value = dictionary.getValue(entry); String url = ""; if (entry.algorithm instanceof ISitedTermSimilarity) { url = ((ISitedTermSimilarity) entry.algorithm).getContextSite(); if (url == null) { url = ""; } } String simil = toString(value.similarity); CSVSupport.writeCell(entry.goalWord, buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell(entry.searchWord, buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell(getAlgorithmName(entry.algorithm), buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell(url, buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell(simil, buffer); CSVSupport.addSeparator(buffer); CSVSupport.writeCell(value.editedDate.toString(), buffer); CSVSupport.addLineEnding(buffer); } } catch (IOException e) { interaction.reportProblem("File I/O Error", e.getMessage()); return false; } finally { try { if (buffer != null) { buffer.close(); } if (fw != null) { fw.close(); } } catch (IOException e) { interaction.reportProblem("File I/O Error on Close", e.getMessage()); return false; } } interaction.setStatusMessage("Export successful"); return true; } protected static double parseDouble(String simil) { try { return Double.parseDouble(simil); } catch (NumberFormatException ex) { return ITermSimilarity.UNKNOWN; } } /** * Replace prevDict with dict after reading the entries from the file. * @param csvFile TODO */ // I (dfm) believe the above is a lie. I think prevDict was already replaced // by dict by the caller, and prevDict is simply a vestigal bit of data that // is passed around and encapsulated in undo and redo forms for no reason // at all. But I'm not sufficiently confident of that diagnosis to zap it // just yet.... public static boolean importDictionary(final Design design, final ISimilarityDictionary dict, final ISimilarityDictionary prevDict, Interaction interaction, IUndoableEditSequence editSeq, String csvFile) { File dataFile = (csvFile != null ? new File(csvFile) : interaction.selectCSVFile()); if (dataFile == null) { return false; } FileReader reader = null; List<String> outputLines = new ArrayList<String>(); try { reader = new FileReader(dataFile); FileUtil.readLines(reader, outputLines); } catch (IOException e) { interaction.reportProblem("File I/O Error", e.getMessage()); return false; } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { interaction.reportProblem("File I/O Error on Close", e.getMessage()); return false; } } if (outputLines.size() == 0) { interaction.reportProblem("Empty file", "Requested .csv file is empty"); return false; } if (outputLines.size() < 3) { interaction.reportProblem("Invalid file", "Requested file is not a valid dictionary file"); return false; } String[] headerCol = CSVSupport.getCells(outputLines.get(0)); if ((headerCol.length != 2) || ! (ISimilarityDictionary.COGTOOL_DICT_HEADER.equals(headerCol[0])) || ! headerCol[1].equals(DICT_CSV_VERSION_0)) { interaction.reportProblem("Invalid file", "Requested file is not a valid dictionary file"); return false; } final Map<DictEntry, DictValue> newEntries = new LinkedHashMap<DictEntry, DictValue>(); for (int i = 2; i < outputLines.size(); i++) { String newLine = outputLines.get(i); String[] cols = CSVSupport.getCells(newLine); // [required] 0 is goal string // [required] 1 is search string // [required] 2 is algorithm name // [optional] 3 is site (for Google algs) or url (for LSA) // [optional] 4 is term space (for LSA) String site = (cols.length > 3) ? cols[3] : ""; String space = (cols.length > 4) ? cols[4] : ""; DictEntry entry = new DictEntry(cols[0], cols[1], getNameAlgorithm(cols[2], site, space)); double similarity; Date editedDate; try { similarity = parseDouble(cols[4]); editedDate = new PersistentDate(PersistentDate.DATE_FORMAT.parse(cols[5])); } catch (Exception e) { throw new RcvrParsingException("Parsing error", e); } DictValue value = new DictValue(similarity, editedDate); newEntries.put(entry, value); } dict.insertEntries(newEntries, false); if (editSeq != null) { editSeq.addEdit(new AUndoableEdit(ProjectLID.ImportDict) { @Override public String getPresentationName() { return IMPORT_DICTIONARY; } @Override public void redo() { super.redo(); if (! NullSafe.equals(prevDict, WidgetAttributes.NO_DICTIONARY)) { design.setAttribute(WidgetAttributes.DICTIONARY_ATTR, dict); } else { dict.insertEntries(newEntries, false); } } @Override public void undo() { super.undo(); if (! NullSafe.equals(prevDict, WidgetAttributes.NO_DICTIONARY)) { design.setAttribute(WidgetAttributes.DICTIONARY_ATTR, prevDict); } else { dict.removeEntries(newEntries); } } }); } if (interaction != null) { interaction.setStatusMessage("Import successful"); } return true; } }