001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences;
003
004import static org.openstreetmap.josm.tools.Utils.equal;
005
006import java.io.File;
007import java.util.regex.Matcher;
008import java.util.regex.Pattern;
009
010import org.openstreetmap.josm.Main;
011
012/**
013 * A source entry primarily used to save the user's selection of mappaint styles,
014 * but also for preset sources.
015 */
016public class SourceEntry {
017
018    /**
019     *  A URL can be anything that MirroredInputStream understands, i.e.
020     *  a local file, http://, or a file from the current jar
021     */
022    public String url;
023
024    /**
025     * Indicates, that {@link #url} is a zip file and the resource is
026     * inside the zip file.
027     */
028    public boolean isZip;
029
030    /**
031     * If {@link #isZip} is true, denotes the path inside the zip file.
032     */
033    public String zipEntryPath;
034
035    /**
036     *  Name is used as a namespace for color preferences and (currently) only
037     *  one file with a name can be loaded at a time. Additional styles must
038     *  either have the same name as the main style or no name at all.
039     *  If no name is provided, it will be set to the default value "standard".
040     *  The name can also be given in the xml file as attribute for the rules tag.
041     *  (This overrides the name given in the preferences, otherwise both
042     *  methods are equivalent.)
043     */
044    public String name;
045
046    /**
047     * A title that can be used as menu entry.
048     */
049    public String title;
050
051    /**
052     * active is a boolean flag that can be used to turn the style on or off
053     * at runtime.
054     */
055    public boolean active;
056
057    public SourceEntry(String url, boolean isZip, String zipEntryPath, String name, String title, boolean active) {
058        this.url = url;
059        this.isZip = isZip;
060        this.zipEntryPath = equal(zipEntryPath, "") ? null : zipEntryPath;
061        this.name = equal(name, "") ? null : name;
062        this.title = equal(title, "") ? null : title;
063        this.active = active;
064    }
065
066    public SourceEntry(String url, String name, String title, Boolean active) {
067        this(url, false, null, name, title, active);
068    }
069
070    public SourceEntry(SourceEntry e) {
071        this.url = e.url;
072        this.isZip = e.isZip;
073        this.zipEntryPath = e.zipEntryPath;
074        this.name = e.name;
075        this.title = e.title;
076        this.active = e.active;
077    }
078
079    @Override
080    public boolean equals(Object obj) {
081        if (obj == null || getClass() != obj.getClass())
082            return false;
083        final SourceEntry other = (SourceEntry) obj;
084        return equal(other.url, url) &&
085                other.isZip == isZip &&
086                equal(other.zipEntryPath, zipEntryPath) &&
087                equal(other.name, name) &&
088                equal(other.title, title) &&
089                other.active == active;
090    }
091
092    @Override
093    public int hashCode() {
094        int hash = 5;
095        hash = 89 * hash + (this.url != null ? this.url.hashCode() : 0);
096        hash = 89 * hash + (this.isZip ? 1 : 0);
097        hash = 89 * hash + (this.zipEntryPath != null ? this.zipEntryPath.hashCode() : 0);
098        hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
099        hash = 89 * hash + (this.title != null ? this.title.hashCode() : 0);
100        hash = 89 * hash + (this.active ? 1 : 0);
101        return hash;
102    }
103
104    @Override
105    public String toString() {
106        return title != null ? title : url;
107    }
108
109    /**
110     * String to show in menus and error messages.
111     * @return Usually the shortdescription, but can be the file name
112     * if no shortdescription is available.
113     */
114    public String getDisplayString() {
115        if (title != null)
116            return title;
117        else
118            return getFileNamePart();
119    }
120
121    /**
122     * extract file part from url, e.g.:
123     * http://www.test.com/file.xml?format=text  --> file.xml
124     */
125    public String getFileNamePart() {
126        Pattern p = Pattern.compile("([^/\\\\]*?)([?].*)?$");
127        Matcher m = p.matcher(url);
128        if (m.find()) {
129            return m.group(1);
130        } else {
131            Main.warn("Unexpected URL format: "+url);
132            return url;
133        }
134    }
135
136    /**
137     * the name / identifier that should be used to save custom color values
138     * and similar stuff to the preference file
139     * @return the identifier; never null. Usually the result is "standard"
140     */
141    public String getPrefName() {
142        return name == null ? "standard" : name;
143    }
144
145    public boolean isLocal() {
146        if (url.startsWith("http://") || url.startsWith("resource://"))
147            return false;
148        return true;
149    }
150
151    public String getLocalSourceDir() {
152        if (!isLocal())
153            return null;
154        File f = new File(url);
155        File dir = f.getParentFile();
156        if (dir == null)
157            return null;
158        return dir.getPath();
159    }
160
161    /**
162     * Returns the parent directory of the resource inside the zip file.
163     *
164     * @return the parent directory of the resource inside the zip file,
165     * "." if zipEntryPath is a top level file; null, if zipEntryPath is null
166     */
167    public String getZipEntryDirName() {
168        if (zipEntryPath == null) return null;
169        File file = new File(zipEntryPath);
170        File dir = file.getParentFile();
171        if (dir == null) return ".";
172        String path = dir.getPath();
173        if (!"/".equals(File.separator)) {
174            path = path.replace(File.separator, "/");
175        }
176        return path;
177    }
178}