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