001// Copyright 2014 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014package org.apache.tapestry5.services; 015 016import java.io.Serializable; 017import java.util.ArrayList; 018import java.util.List; 019 020/** 021 * Class that encapsulates information about a component library, going beyond what a library mapping 022 * provides. 023 * 024 * @see LibraryMapping 025 * @see SourceUrlResolver 026 * @since 5.4 027 */ 028public final class ComponentLibraryInfo implements Serializable 029{ 030 private static final long serialVersionUID = 1L; 031 032 private LibraryMapping libraryMapping; 033 034 private SourceUrlResolver sourceUrlResolver; 035 036 private String name, description, homepageUrl, documentationUrl, sourceBrowseUrl, issueTrackerUrl, sourceRootUrl, 037 javadocUrl, groupId, artifactId, version, tapestryVersion; 038 039 private List<String> tags = new ArrayList<String>(); 040 041 /** 042 * Returns the actual name of the component library (not the identifier). 043 * For example, "Tapestry 5 Core Library". 044 */ 045 public String getName() 046 { 047 return name; 048 } 049 050 /** 051 * Returns a description of the component library. 052 * For example, "The set of components, pages and mixins provided by Tapestry out-of-the-box.". 053 */ 054 public String getDescription() 055 { 056 return description; 057 } 058 059 /** 060 * Returns the URL of the homepage of the component library. 061 * For example, "http://tapestry.apache.org". 062 */ 063 public String getHomepageUrl() 064 { 065 return homepageUrl; 066 } 067 068 /** 069 * Returns the URL of the component library's documentation. 070 * For example, "http://tapestry.apache.org/documentation.html". 071 */ 072 public String getDocumentationUrl() 073 { 074 return documentationUrl; 075 } 076 077 /** 078 * Returns the URL where the component library's source can be browsed. 079 * For example, "http://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=summary". 080 */ 081 public String getSourceBrowseUrl() 082 { 083 return sourceBrowseUrl; 084 } 085 086 /** 087 * Returns the URL where the root folder of component library's source can be found. 088 * For example, "http://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=tree;f=tapestry-core/src/main/java/". 089 */ 090 public String getSourceRootUrl() 091 { 092 return sourceRootUrl; 093 } 094 095 /** 096 * Returns the URL of the component's library issue tracker. 097 * For example, "http://issues.apache.org/jira/browse/TAP5". 098 */ 099 public String getIssueTrackerUrl() 100 { 101 return issueTrackerUrl; 102 } 103 104 /** 105 * Returns the URL of the component library's JavaDoc URL. 106 * For example, "http://tapestry.apache.org/current/apidocs/" 107 */ 108 public String getJavadocUrl() 109 { 110 return javadocUrl; 111 } 112 113 /** 114 * Returns the component library's group id for dependency management tools like Maven and Gradle. 115 * For example, "org.apache.tapestry". 116 * @see #artifactId 117 * @see #version 118 */ 119 public String getGroupId() 120 { 121 return groupId; 122 } 123 124 /** 125 * Returns the component library's group id for dependency management tools like Maven and Gradle. 126 * For example, "tapestry-core". 127 * @see #groupId 128 * @see #version 129 */ 130 public String getArtifactId() 131 { 132 return artifactId; 133 } 134 135 /** 136 * Returns the component library version. For example, "5.4.0". 137 * @see #artifactId 138 * @see #groupId 139 */ 140 public String getVersion() 141 { 142 return version; 143 } 144 145 /** 146 * Returns the Tapestry version used by this component library. For example, "5.4.0". 147 */ 148 public String getTapestryVersion() 149 { 150 return tapestryVersion; 151 } 152 153 /** 154 * Returns the tags associated which describe this component library. 155 * Use just lowercase letters, numbers and dashes. 156 */ 157 public List<String> getTags() 158 { 159 return tags; 160 } 161 162 /** 163 * Returns an URL decribing the dependency management information for this component library. 164 */ 165 public String getDependencyManagementInfoUrl() 166 { 167 String url = null; 168 if (isDependencyManagementInfoPresent()) 169 { 170 url = String.format( 171 "http://search.maven.org/#artifactdetails|%s|%s|version=%s|jar", 172 getGroupId(), getArtifactId(), getVersion()); 173 } 174 return url; 175 } 176 177 public void setName(String name) 178 { 179 if (this.name != null) throwExceptionIfAlreadySet("name", name); 180 this.name = name; 181 } 182 183 public void setDescription(String description) 184 { 185 if (this.description != null) throwExceptionIfAlreadySet("description", description); 186 this.description = description; 187 } 188 189 public void setHomepageUrl(String homepageUrl) 190 { 191 if (this.homepageUrl != null) throwExceptionIfAlreadySet("homepageUrl", homepageUrl); 192 this.homepageUrl = homepageUrl; 193 } 194 195 public void setDocumentationUrl(String documentationUrl) 196 { 197 if (this.documentationUrl != null) throwExceptionIfAlreadySet("documentationUrl", documentationUrl); 198 this.documentationUrl = documentationUrl; 199 } 200 201 public void setSourceBrowseUrl(String sourceBrowseUrl) 202 { 203 if (this.sourceBrowseUrl != null) throwExceptionIfAlreadySet("sourceBrowseUrl", sourceBrowseUrl); 204 this.sourceBrowseUrl = sourceBrowseUrl; 205 } 206 207 public void setSourceRootUrl(String sourceRootUrl) 208 { 209 if (this.sourceRootUrl != null) throwExceptionIfAlreadySet("sourceRootUrl", sourceRootUrl); 210 this.sourceRootUrl = sourceRootUrl; 211 } 212 213 public void setJavadocUrl(String javadocUrl) 214 { 215 if (this.javadocUrl != null) throwExceptionIfAlreadySet("javadocUrl", javadocUrl); 216 this.javadocUrl = javadocUrl; 217 } 218 219 public void setVersion(String version) 220 { 221 if (this.version != null) throwExceptionIfAlreadySet("version", version); 222 this.version = version; 223 } 224 225 public void setTapestryVersion(String tapestryVersion) 226 { 227 if (this.tapestryVersion != null) throwExceptionIfAlreadySet("tapestryVersion", version); 228 this.tapestryVersion = tapestryVersion; 229 } 230 231 public void setGroupId(String groupId) 232 { 233 if (this.groupId != null) throwExceptionIfAlreadySet("groupId", artifactId); 234 this.groupId = groupId; 235 } 236 237 public void setArtifactId(String artifactId) 238 { 239 if (this.artifactId != null) throwExceptionIfAlreadySet("artifactId", artifactId); 240 this.artifactId = artifactId; 241 } 242 243 public void setIssueTrackerUrl(String issueTrackingUrl) 244 { 245 if (this.issueTrackerUrl != null) throwExceptionIfAlreadySet("issueTrackingUrl", issueTrackingUrl); 246 this.issueTrackerUrl = issueTrackingUrl; 247 } 248 249 public void setTags(List<String> tags) 250 { 251 if (this.tags != null) throwExceptionIfAlreadySet("tags", tags); 252 this.tags = tags; 253 } 254 255 public void setLibraryMapping(LibraryMapping libraryMapping) 256 { 257 if (this.libraryMapping != null) throwExceptionIfAlreadySet("libraryMapping", libraryMapping); 258 this.libraryMapping = libraryMapping; 259 } 260 261 public void setSourceUrlResolver(SourceUrlResolver sourceUrlResolver) 262 { 263 if (this.sourceUrlResolver != null) throwExceptionIfAlreadySet("sourceUrlResolver", sourceUrlResolver); 264 this.sourceUrlResolver = sourceUrlResolver; 265 if (sourceUrlResolver != null) 266 { 267 sourceUrlResolver.setRootUrl(getSourceRootUrl()); 268 } 269 } 270 271 /** 272 * Tells whether full dependency management info (group id, artifact id and version) are present. 273 */ 274 public boolean isDependencyManagementInfoPresent() 275 { 276 return groupId != null && artifactId != null && version != null; 277 } 278 279 /** 280 * Given a logical name, tells whether a given component, page or mixin is part of this 281 * component library. 282 */ 283 public boolean isPart(String logicalName) 284 { 285 return logicalName.startsWith(libraryMapping.libraryName + "/") || 286 (libraryMapping.libraryName.equals("") && logicalName.indexOf("/") < 0); 287 } 288 289 /** 290 * Returns the JavaDoc URL for a given class or <code>null</code> if the root JavaDoc URL was 291 * not provided. 292 * @param className the fully qualified class name. 293 */ 294 public String getJavadocUrl(String className) 295 { 296 String url = null; 297 String baseUrl = getJavadocUrl(); 298 if (baseUrl != null) 299 { 300 if (!baseUrl.endsWith("/")) 301 { 302 baseUrl = baseUrl + "/"; 303 } 304 url = baseUrl + className.replace('.', '/') + ".html"; 305 } 306 return url; 307 } 308 309 /** 310 * Returns the URL where the source of this class can be found or <code>null</code> if 311 * not available. This implementation delegates to {@link SourceUrlResolver} if set. 312 * @param className the fully qualified class name. 313 */ 314 public String getSourceUrl(String className) 315 { 316 String url = null; 317 if (sourceRootUrl != null) 318 { 319 if (sourceUrlResolver == null) 320 { 321 sourceUrlResolver = new DefaultSourceUrlResolver(); 322 sourceUrlResolver.setRootUrl(sourceRootUrl); 323 } 324 url = sourceUrlResolver.resolve(className); 325 } 326 return url; 327 } 328 329 private void throwExceptionIfAlreadySet(String propertyName, Object propertyValue) 330 { 331 if (propertyValue != null) 332 { 333 throw new RuntimeException(String.format("%s already has a value of \"%s\"", propertyName, propertyValue)); 334 } 335 } 336 337 /** 338 * Interface that provides the source URL for a given {@link ComponentLibraryInfo}. 339 */ 340 public static interface SourceUrlResolver 341 { 342 /** 343 * Returns the source URL for a given class. 344 * @param className the fully qualified class name. 345 */ 346 String resolve(String className); 347 348 /** 349 * Sets the source root URL. This method will be invoked by {@link ComponentLibraryInfo#setSourceBrowseUrl(String)}. 350 */ 351 void setRootUrl(String url); 352 353 } 354 355 /** 356 * Default {@link SourceUrlResolver} implementation. 357 */ 358 public static class DefaultSourceUrlResolver implements SourceUrlResolver 359 { 360 361 private String sourceRootUrl; 362 363 @Override 364 public String resolve(String className) 365 { 366 return sourceRootUrl + className.replace('.', '/') + ".java"; 367 } 368 369 @Override 370 public void setRootUrl(String url) 371 { 372 this.sourceRootUrl = url; 373 if (sourceRootUrl.startsWith("scm:")) 374 { 375 this.sourceRootUrl = this.sourceRootUrl.replaceFirst("[^:]+:[^:]+:", ""); 376 } 377 } 378 379 } 380 381 public String toString() { 382 return String.format("ComponentLibraryInfo[%s]", libraryMapping); 383 } 384 385}