/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org Copyright (c) 2013-16 The Processing Foundation Copyright (c) 2011-12 Ben Fry and Casey Reas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.app.contrib; import java.io.File; import java.util.Arrays; import java.util.List; import processing.core.PApplet; import processing.data.StringDict; import processing.data.StringList; import processing.app.Language; import processing.app.Util; abstract public class Contribution { static final String IMPORTS_PROPERTY = "imports"; static final String CATEGORIES_PROPERTY = "categories"; static final String MODES_PROPERTY = "modes"; static final String AUTHORS_PROPERTY = "authors"; static final String SPECIAL_CATEGORY = "Starred"; static final String UNKNOWN_CATEGORY = "Unknown"; static final List validCategories = Arrays.asList("3D", "Animation", "Data", "Geometry", "GUI", "Hardware", "I/O", "Math", "Simulation", "Sound", SPECIAL_CATEGORY, "Typography", "Utilities", "Video & Vision", "Other"); static final String FOUNDATION_AUTHOR = "The Processing Foundation"; protected StringList categories; // "Sound", "Typography" protected String name; // "pdf" or "PDF Export" protected String authors; // [Ben Fry](http://benfry.com) protected String url; // http://processing.org protected String sentence; // Write graphics to PDF files. protected String paragraph; // <paragraph length description for site> protected int version; // 102 protected String prettyVersion; // "1.0.2" protected long lastUpdated; // 1402805757 protected int minRevision; // 0 protected int maxRevision; // 227 protected StringList imports; // pdf.export,pdf.convert.common (list of packages, not imports) // "Sound", "Utilities"... see valid list in ContributionListing protected StringList getCategories() { return categories; } protected String getCategoryStr() { StringBuilder sb = new StringBuilder(); for (String category : categories) { sb.append(category); sb.append(','); } sb.deleteCharAt(sb.length()-1); // delete last comma return sb.toString(); } protected boolean hasCategory(String category) { if (category != null) { for (String c : categories) { if (category.equalsIgnoreCase(c)) { return true; } } } return false; } // pdf.export.*,pdf.convert.common.* protected StringList getImports() { return imports; } /* protected String getImportStr() { if (imports == null || imports.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); for (String importName : imports) { sb.append(importName); sb.append(','); } sb.deleteCharAt(sb.length() - 1); // delete last comma return sb.toString(); } */ protected boolean hasImport(String importName) { if (imports != null && importName != null) { for (String c : imports) { if (importName.equals(c)) { return true; } } } return false; } // "pdf" or "PDF Export" public String getName() { return name; } // "[Ben Fry](http://benfry.com/)" public String getAuthorList() { return authors; } // "http://processing.org" public String getUrl() { return url; } // "Write graphics to PDF files." public String getSentence() { return sentence; } // <paragraph length description for site> public String getParagraph() { return paragraph; } // 102 public int getVersion() { return version; } public void setPrettyVersion(String pretty) { if (pretty != null) { // some entries were written as "null", causing that to show in the ui if (pretty.equals("null") || pretty.length() == 0) { pretty = null; } } prettyVersion = pretty; } // "1.0.2" or null if not present public String getPrettyVersion() { return prettyVersion; } // returns prettyVersion, or "" if null public String getBenignVersion() { return (prettyVersion != null) ? prettyVersion : ""; } // 1402805757 public long getLastUpdated() { return lastUpdated; } // 0 public int getMinRevision() { return minRevision; } // 227 public int getMaxRevision() { return maxRevision; } public boolean isCompatible(int versionNum) { return ((maxRevision == 0 || versionNum <= maxRevision) && versionNum >= minRevision); } abstract public ContributionType getType(); public String getTypeName() { return getType().toString(); } abstract public boolean isInstalled(); // /** // * Returns true if the type of contribution requires the PDE to restart // * when being added or removed. // */ // public boolean requiresRestart() { // return getType() == ContributionType.TOOL || getType() == ContributionType.MODE; // } boolean isRestartFlagged() { return false; } /** Overridden by LocalContribution. */ boolean isDeletionFlagged() { return false; } boolean isUpdateFlagged() { return false; } /** * Returns true if the contribution is a starred/recommended contribution, * or is by the Processing Foundation. */ boolean isSpecial() { if (authors != null && authors.contains(FOUNDATION_AUTHOR)) { return true; } if (categories != null && categories.hasValue(SPECIAL_CATEGORY)) { return true; } return false; } public boolean isFoundation() { return FOUNDATION_AUTHOR.equals(authors); } public StringDict loadProperties(File contribFolder) { return loadProperties(contribFolder, getType()); } static public StringDict loadProperties(File contribFolder, ContributionType type) { File propertiesFile = new File(contribFolder, type.getPropertiesName()); if (propertiesFile.exists()) { return Util.readSettings(propertiesFile); } return null; } /** * @return a single element list with "Unknown" as the category. */ static StringList unknownCategoryList() { return new StringList(UNKNOWN_CATEGORY); } /** * @return the list of categories that this contribution is part of * (e.g. "Typography / Geometry"). "Unknown" if the category null. */ static StringList parseCategories(StringDict properties) { StringList outgoing = new StringList(); String categoryStr = properties.get(CATEGORIES_PROPERTY); if (categoryStr == null) { categoryStr = properties.get("category"); // try the old way } if (categoryStr != null) { // Can't use splitTokens() because the names sometimes have spaces String[] listing = PApplet.trim(PApplet.split(categoryStr, ',')); for (String category : listing) { if (validCategories.contains(category)) { category = translateCategory(category); outgoing.append(category); } } } if (outgoing.size() == 0) { return unknownCategoryList(); } return outgoing; } /** * Returns the list of imports specified by this library author. Only * necessary for library authors that want to override the default behavior * of importing all packages in their library. * @return null if no entries found */ static StringList parseImports(StringDict properties) { StringList outgoing = new StringList(); String importStr = properties.get(IMPORTS_PROPERTY); if (importStr != null) { String[] importList = PApplet.trim(PApplet.split(importStr, ',')); for (String importName : importList) { if (!importName.isEmpty()) { outgoing.append(importName); } } } return (outgoing.size() > 0) ? outgoing : null; } /** * Helper function that creates a StringList of the compatible Modes * for this Contribution. */ static StringList parseModeList(StringDict properties) { String unparsedModes = properties.get(MODES_PROPERTY); // Workaround for 3.0 alpha/beta bug for 3.0b2 if ("null".equals(unparsedModes)) { properties.remove(MODES_PROPERTY); unparsedModes = null; } StringList outgoing = new StringList(); if (unparsedModes != null) { outgoing.append(PApplet.trim(PApplet.split(unparsedModes, ','))); } return outgoing; } static private String translateCategory(String cat) { // Converts Other to other, I/O to i_o, Video & Vision to video_vision String cleaned = cat.replaceAll("[\\W]+", "_").toLowerCase(); return Language.text("contrib.category." + cleaned); } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof Contribution) { Contribution that = (Contribution) o; return name.toLowerCase().equals(that.name.toLowerCase()); } return false; } @Override public int hashCode() { return name.toLowerCase().hashCode(); } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . public interface Filter { boolean matches(Contribution contrib); } }