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 (this == obj) return true; 112 if (obj == null || getClass() != obj.getClass()) return false; 113 SourceEntry that = (SourceEntry) obj; 114 return isZip == that.isZip && 115 active == that.active && 116 Objects.equals(url, that.url) && 117 Objects.equals(zipEntryPath, that.zipEntryPath) && 118 Objects.equals(name, that.name) && 119 Objects.equals(title, that.title); 120 } 121 122 @Override 123 public int hashCode() { 124 return Objects.hash(url, isZip, zipEntryPath, name, title, active); 125 } 126 127 @Override 128 public String toString() { 129 return title != null ? title : url; 130 } 131 132 /** 133 * String to show in menus and error messages. 134 * @return Usually the shortdescription, but can be the file name 135 * if no shortdescription is available. 136 */ 137 public String getDisplayString() { 138 if (title != null) 139 return title; 140 else 141 return getFileNamePart(); 142 } 143 144 /** 145 * Extracts file part from url, e.g.: 146 * <code>http://www.test.com/file.xml?format=text --> file.xml</code> 147 * @return The filename part of the URL 148 */ 149 public String getFileNamePart() { 150 Pattern p = Pattern.compile("([^/\\\\]*?)([?].*)?$"); 151 Matcher m = p.matcher(url); 152 if (m.find()) { 153 return m.group(1); 154 } else { 155 Main.warn("Unexpected URL format: "+url); 156 return url; 157 } 158 } 159 160 /** 161 * the name / identifier that should be used to save custom color values 162 * and similar stuff to the preference file 163 * @return the identifier; never null. Usually the result is "standard" 164 */ 165 public String getPrefName() { 166 return name == null ? "standard" : name; 167 } 168 169 /** 170 * Determines if this source denotes a file on a local filesystem. 171 * @return {@code true} if the source is a local file 172 */ 173 public boolean isLocal() { 174 return Utils.isLocalUrl(url); 175 } 176 177 /** 178 * Return the source directory, only for local files. 179 * @return The source directory, or {@code null} if this file isn't local, or does not have a parent 180 * @since 7276 181 */ 182 public File getLocalSourceDir() { 183 if (!isLocal()) 184 return null; 185 return new File(url).getParentFile(); 186 } 187 188 /** 189 * Returns the parent directory of the resource inside the zip file. 190 * 191 * @return the parent directory of the resource inside the zip file, 192 * "." if zipEntryPath is a top level file; null, if zipEntryPath is null 193 */ 194 public String getZipEntryDirName() { 195 if (zipEntryPath == null) return null; 196 File file = new File(zipEntryPath); 197 File dir = file.getParentFile(); 198 if (dir == null) return "."; 199 String path = dir.getPath(); 200 if (!"/".equals(File.separator)) { 201 path = path.replace(File.separator, "/"); 202 } 203 return path; 204 } 205}