/* -*- 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);
}
}