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