diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java index 939a3f399..c16506c89 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java @@ -465,7 +465,7 @@ protected Optional getLowerBound( ArtifactVersion version, Optional extends VersionsReportRe protected ArtifactVersionsCache allUpdatesCache = new ArtifactVersionsCache( AbstractVersionDetails::getAllUpdates ); + protected final SinkEventAttributes headerAttributes + = new SinkEventAttributeSet( SinkEventAttributes.WIDTH, "30%" ); + protected AbstractVersionsReportRenderer( I18N i18n, Sink sink, Locale locale, String bundleName, T model ) { super( sink, i18n, locale, bundleName ); @@ -139,18 +146,17 @@ protected void renderOverviewTableRow( Q stats ) renderStatRow( "report.overview.numNewerMajorAvailable", stats.getMajor(), false ); } + /** + * Renders one table row for the given statistics. + * @param textKey the key of the text to be rendered. + * @param statCount the number of artifacts with the given stat. + * @param forceSuccessIcon if true, the success icon will be rendered regardless. + */ protected void renderStatRow( String textKey, int statCount, boolean forceSuccessIcon ) { sink.tableRow(); sink.tableCell(); - if ( statCount == 0 || forceSuccessIcon ) - { - renderSuccessIcon(); - } - else - { - renderWarningIcon(); - } + renderIcon( statCount == 0 || forceSuccessIcon ); sink.tableCell_(); sink.tableCell(); sink.text( getText( textKey ) ); @@ -161,6 +167,22 @@ protected void renderStatRow( String textKey, int statCount, boolean forceSucces sink.tableRow_(); } + /** + * Renders the success or warning icon. + * @param success if true, the success icon will be rendered, otherwise the warning icon will be rendered. + */ + protected void renderIcon( boolean success ) + { + if ( success ) + { + renderSuccessIcon(); + } + else + { + renderWarningIcon(); + } + } + /** * Computes the {@linkplain OverviewStats} object needed to render the summary table row * @param concrete {@linkplain OverviewStats} class @@ -207,101 +229,108 @@ protected void renderSummaryTableHeader( boolean hasScope, boolean hasType ) "report.latestIncremental", "report.latestMinor", "report.latestMajor" ); } - protected void renderSummaryTableRow( Dependency artifact, ArtifactVersions details, - boolean includeScope ) + protected void renderSummaryTableRow( Dependency artifact, ArtifactVersions details, boolean includeScope ) { ArtifactVersion[] allUpdates = allUpdatesCache.get( details, empty() ); boolean upToDate = allUpdates == null || allUpdates.length == 0; sink.tableRow(); - sink.tableCell(); - if ( upToDate ) - { - renderSuccessIcon(); - } - else - { - renderWarningIcon(); - } - sink.tableCell_(); - sink.tableCell(); - sink.text( artifact.getGroupId() ); - sink.tableCell_(); - sink.tableCell(); - sink.text( artifact.getArtifactId() ); - sink.tableCell_(); - sink.tableCell(); - sink.text( artifact.getVersion() ); - sink.tableCell_(); - if ( includeScope ) - { - sink.tableCell(); - sink.text( artifact.getScope() ); - sink.tableCell_(); - } - sink.tableCell(); - sink.text( artifact.getClassifier() ); - sink.tableCell_(); - sink.tableCell(); - sink.text( artifact.getType() ); - sink.tableCell_(); - - sink.tableCell(); - if ( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); sink.tableCell(); - if ( newestUpdateCache.get( details, of( INCREMENTAL ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( INCREMENTAL ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); - - sink.tableCell(); - if ( newestUpdateCache.get( details, of( MINOR ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( MINOR ) ).toString() ); - safeBold_(); - } + renderIcon( upToDate ); sink.tableCell_(); - sink.tableCell(); - if ( newestUpdateCache.get( details, of( MAJOR ) ) != null ) + renderCells( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() ); + if ( includeScope ) { - safeBold(); - sink.text( newestUpdateCache.get( details, of( MAJOR ) ).toString() ); - safeBold_(); + renderCell( artifact.getScope() ); } - sink.tableCell_(); + renderCells( artifact.getClassifier(), artifact.getType() ); + renderNewestVersions( details ); sink.tableRow_(); } + /** + * Renders the newest versions for the given artifact. + * @param details the artifact for which to render the newest versions. + */ + protected void renderNewestVersions( AbstractVersionDetails details ) + { + renderBoldCell( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ) ); + renderBoldCell( newestUpdateCache.get( details, of( INCREMENTAL ) ) ); + renderBoldCell( newestUpdateCache.get( details, of( MINOR ) ) ); + renderBoldCell( newestUpdateCache.get( details, of( MAJOR ) ) ); + } + @SuppressWarnings( "checkstyle:MethodLength" ) protected void renderDependencyDetailTable( Dependency artifact, ArtifactVersions details, boolean includeScope ) { ArtifactVersion[] allUpdates = allUpdatesCache.get( details, empty() ); boolean upToDate = allUpdates == null || allUpdates.length == 0; - final SinkEventAttributes headerAttributes = new SinkEventAttributeSet(); - headerAttributes.addAttribute( SinkEventAttributes.WIDTH, "70%" ); - final SinkEventAttributes cellAttributes = new SinkEventAttributeSet(); - headerAttributes.addAttribute( SinkEventAttributes.WIDTH, "30%" ); sink.table(); sink.tableRows( new int[] { Sink.JUSTIFY_RIGHT, Sink.JUSTIFY_LEFT }, false ); + + renderTwoCellsRow( "report.status", () -> renderStatus( details ) ); + renderTwoCellsRow( "report.groupId", artifact.getGroupId() ); + renderTwoCellsRow( "report.artifactId", artifact.getArtifactId() ); + renderTwoCellsRow( "report.currentVersion", artifact.getVersion() ); + if ( includeScope ) + { + renderTwoCellsRow( "report.scope", artifact.getScope() ); + } + renderTwoCellsRow( "report.classifier", artifact.getClassifier() ); + renderTwoCellsRow( "report.type", artifact.getType() ); + if ( !upToDate ) + { + renderTwoCellsRow( "report.updateVersions", () -> renderVersions( allUpdates, details ) ); + } + + sink.tableRows_(); + sink.table_(); + } + + /** + * Renders a row of two cells, the first cell being an header and the second cell being a non-header cell. + * @param textKey the key of the text to be rendered. + * @param textValue the value of the text to be rendered. + */ + protected void renderTwoCellsRow( String textKey, String textValue ) + { sink.tableRow(); sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.status" ) ); + sink.text( getText( textKey ) ); + sink.tableHeaderCell_(); + sink.tableCell(); + sink.text( textValue ); + sink.tableCell_(); + sink.tableRow_(); + } + + /** + * Renders a row of two cells, the first cell being an header and the second cell being a non-header cell. + * @param textKey the key of the text to be rendered. + * @param runnable the runnable to be executed to render the second cell content. + */ + protected void renderTwoCellsRow( String textKey, Runnable runnable ) + { + sink.tableRow(); + sink.tableHeaderCell( headerAttributes ); + sink.text( getText( textKey ) ); sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); + sink.tableCell(); + runnable.run(); + sink.tableCell_(); + sink.tableRow_(); + } + + /** + * Renders the status of the given artifact. + * @param details the artifact for which to render the status. + */ + protected void renderStatus( AbstractVersionDetails details ) + { if ( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ) != null ) { renderWarningIcon(); @@ -332,111 +361,82 @@ else if ( newestUpdateCache.get( details, of( MAJOR ) ) != null ) sink.nonBreakingSpace(); sink.text( getText( "report.noUpdatesAvailable" ) ); } - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.groupId" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( artifact.getGroupId() ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.artifactId" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( artifact.getArtifactId() ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.currentVersion" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( artifact.getVersion() ); - sink.tableCell_(); - sink.tableRow_(); - if ( includeScope ) + } + + private List getArtifactVersionRange( AbstractVersionDetails details ) + { + try { - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.scope" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( artifact.getScope() ); - sink.tableCell_(); - sink.tableRow_(); + String spec = details.getCurrentVersion().toString(); + VersionRange range = VersionRange.createFromVersionSpec( spec ); + return range.getRestrictions(); } - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.classifier" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( artifact.getClassifier() ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.type" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( artifact.getType() ); - sink.tableCell_(); - sink.tableRow_(); - if ( !upToDate ) + catch ( InvalidVersionSpecificationException ignored ) + { + ignored.printStackTrace( System.err ); + } + return Collections.EMPTY_LIST; + } + + /** + * Renders the list of versions that are available for the given artifact or property. + * @param allUpdates the list of all updates available. + * @param details TODO. + */ + protected void renderVersions( ArtifactVersion[] allUpdates, AbstractVersionDetails details ) + { + List versionRange = getArtifactVersionRange( details ); + boolean someNotAllowed = false; + for ( int i = 0; i < allUpdates.length; i++ ) { - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.updateVersions" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - for ( int i = 0; i < allUpdates.length; i++ ) + if ( i > 0 ) { - if ( i > 0 ) - { - sink.lineBreak(); - } - String label = getLabel( allUpdates[i], details ); - if ( label != null ) - { - safeBold(); - } - sink.text( allUpdates[i].toString() ); - if ( label != null ) + sink.lineBreak(); + } + // if candidate version in range, display no star. + ArtifactVersion candidate = allUpdates[i]; + boolean allowed = versionRange.stream().anyMatch( restriction -> + details.isVersionInRestriction( restriction, candidate ) ); + String label = getLabel( allUpdates[i], details ); + if ( !allowed ) + { + sink.text( "* " ); + someNotAllowed = true; + } + if ( allowed && label != null ) + { + safeBold(); + } + sink.text( allUpdates[i].toString() ); + if ( label != null ) + { + if ( allowed ) { safeBold_(); - sink.nonBreakingSpace(); - safeItalic(); - sink.text( label ); - safeItalic_(); } + sink.nonBreakingSpace(); + safeItalic(); + sink.text( label ); + safeItalic_(); } - sink.tableCell_(); - sink.tableRow_(); } - sink.tableRows_(); - sink.table_(); + if ( someNotAllowed ) + { + sink.lineBreak(); + sink.lineBreak(); + sink.text( "* " ); + safeItalic(); + sink.text( getText( "report.excludedVersion" ) ); + safeItalic_(); + } } /** - * Renders a table header containing elements denoted by the given keys - * @param keys variable argument list containing keys of the property file to retrieve the - * headers from + * Returns a text label to describe if the given version is a major, minor, incremental or subincremental update. + * @param version the version to describe. + * @param details the artifact for which to render the versions. + * @return a text label to describe if the given version is a major, minor, incremental or subincremental update. */ - protected void renderTableHeaderCells( String... keys ) - { - Arrays.stream( keys ) - .map( this::getText ) - .forEachOrdered( str -> - { - sink.tableHeaderCell(); - sink.text( str ); - sink.tableHeaderCell_(); - } ); - } - protected String getLabel( ArtifactVersion version, AbstractVersionDetails details ) { @@ -462,4 +462,5 @@ protected String getLabel( ArtifactVersion version, AbstractVersionDetails detai return null; } + } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java index 2d8948280..8072e3119 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java @@ -98,4 +98,5 @@ protected void renderDependencyDetail( Dependency artifact, ArtifactVersions det renderDependencyDetailTable( artifact, details, true ); sink.section2_(); } + } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java index c878110a8..bf2fd24de 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java @@ -26,8 +26,6 @@ import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.doxia.sink.Sink; -import org.apache.maven.doxia.sink.SinkEventAttributes; -import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; import org.apache.maven.model.Dependency; import org.codehaus.mojo.versions.api.ArtifactVersions; import org.codehaus.mojo.versions.api.PluginUpdatesDetails; @@ -35,11 +33,6 @@ import org.codehaus.plexus.i18n.I18N; import static java.util.Optional.empty; -import static java.util.Optional.of; -import static org.codehaus.mojo.versions.api.Segment.INCREMENTAL; -import static org.codehaus.mojo.versions.api.Segment.MAJOR; -import static org.codehaus.mojo.versions.api.Segment.MINOR; -import static org.codehaus.mojo.versions.api.Segment.SUBINCREMENTAL; /** * @since 1.0-beta-1 @@ -153,79 +146,12 @@ protected void renderSummaryTableRow( Dependency artifact, PluginUpdatesDetails sink.tableRow(); sink.tableCell(); - if ( upToDate ) - { - renderSuccessIcon(); - } - else - { - renderWarningIcon(); - } - sink.tableCell_(); - sink.tableCell(); - sink.text( artifact.getGroupId() ); - sink.tableCell_(); - sink.tableCell(); - sink.text( artifact.getArtifactId() ); - sink.tableCell_(); - sink.tableCell(); - if ( !details.isArtifactUpdateAvailable() ) - { - safeBold(); - } - sink.text( artifact.getVersion() ); - if ( !details.isArtifactUpdateAvailable() ) - { - safeBold_(); - } - sink.tableCell_(); - sink.tableCell(); - if ( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); - - sink.tableCell(); - if ( newestUpdateCache.get( details, of( INCREMENTAL ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( INCREMENTAL ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); - - sink.tableCell(); - if ( newestUpdateCache.get( details, of( MINOR ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( MINOR ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); - - sink.tableCell(); - if ( newestUpdateCache.get( details, of( MAJOR ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( MAJOR ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); - - sink.tableCell(); - if ( details.isDependencyUpdateAvailable() ) - { - renderWarningIcon(); - } - else - { - renderSuccessIcon(); - } - sink.tableCell_(); + renderIcon( upToDate ); + renderCells( artifact.getGroupId(), artifact.getArtifactId() ); + renderBoldCell( upToDate, artifact.getVersion() ); + renderNewestVersions( details ); + renderIcon( !details.isDependencyUpdateAvailable() ); sink.tableRow_(); } @@ -260,110 +186,24 @@ private void renderPluginDetail( Dependency artifact, PluginUpdatesDetails detai private void renderPluginDetailTable( PluginUpdatesDetails details ) { - // warning: using caches here may break plugin report + // warning: using caches here might break plugin report ArtifactVersion[] allUpdates = details.getAllUpdates( empty() ); boolean upToDate = allUpdates == null || allUpdates.length == 0; - final SinkEventAttributes headerAttributes = new SinkEventAttributeSet(); - headerAttributes.addAttribute( SinkEventAttributes.WIDTH, "70%" ); - final SinkEventAttributes cellAttributes = new SinkEventAttributeSet(); - headerAttributes.addAttribute( SinkEventAttributes.WIDTH, "30%" ); sink.table(); sink.tableRows( new int[] { Sink.JUSTIFY_RIGHT, Sink.JUSTIFY_LEFT }, false ); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.status" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - if ( details.getNewestUpdate( of( SUBINCREMENTAL ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.otherUpdatesAvailable" ) ); - } - else if ( details.getNewestUpdate( of( INCREMENTAL ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.incrementalUpdatesAvailable" ) ); - } - else if ( details.getNewestUpdate( of( MINOR ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.minorUpdatesAvailable" ) ); - } - else if ( details.getNewestUpdate( of( MAJOR ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.majorUpdatesAvailable" ) ); - } - else - { - renderSuccessIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.noUpdatesAvailable" ) ); - } - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.groupId" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( details.getGroupId() ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.artifactId" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( details.getArtifactId() ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.currentVersion" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( details.getVersion() ); - sink.tableCell_(); - sink.tableRow_(); + + renderTwoCellsRow( "report.status", () -> renderStatus( details ) ); + renderTwoCellsRow( "report.groupId", details.getGroupId() ); + renderTwoCellsRow( "report.artifactId", details.getArtifactId() ); + renderTwoCellsRow( "report.currentVersion", details.getVersion() ); if ( !upToDate ) { - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.updateVersions" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - for ( int i = 0; i < allUpdates.length; i++ ) - { - if ( i > 0 ) - { - sink.lineBreak(); - } - String label = getLabel( allUpdates[i], details ); - if ( label != null ) - { - safeBold(); - } - sink.text( allUpdates[i].toString() ); - if ( label != null ) - { - safeBold_(); - sink.nonBreakingSpace(); - safeItalic(); - sink.text( label ); - safeItalic_(); - } - } - sink.tableCell_(); - sink.tableRow_(); + renderTwoCellsRow( "report.updateVersions", () -> renderVersions( allUpdates, details ) ); } + sink.tableRows_(); sink.table_(); } -} +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java index c68656e6c..e925ccb20 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java @@ -19,31 +19,19 @@ * under the License. */ -import java.util.HashSet; import java.util.Locale; import java.util.Map; -import java.util.Set; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.versioning.ArtifactVersion; -import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; -import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.doxia.sink.Sink; -import org.apache.maven.doxia.sink.SinkEventAttributes; -import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.ArtifactAssociation; import org.codehaus.mojo.versions.api.PropertyVersions; import org.codehaus.mojo.versions.reporting.model.PropertyUpdatesModel; import org.codehaus.plexus.i18n.I18N; -import org.codehaus.plexus.util.StringUtils; import static java.util.Optional.empty; -import static java.util.Optional.of; -import static org.codehaus.mojo.versions.api.Segment.INCREMENTAL; -import static org.codehaus.mojo.versions.api.Segment.MAJOR; -import static org.codehaus.mojo.versions.api.Segment.MINOR; -import static org.codehaus.mojo.versions.api.Segment.SUBINCREMENTAL; /** * @since 1.0-beta-1 @@ -120,58 +108,13 @@ private void renderPropertySummaryTableRow( Property property, PropertyVersions boolean upToDate = allUpdates == null || allUpdates.length == 0; sink.tableRow(); - sink.tableCell(); - if ( upToDate ) - { - renderSuccessIcon(); - } - else - { - renderWarningIcon(); - } - sink.tableCell_(); - sink.tableCell(); - sink.text( "${" + property.getName() + "}" ); - sink.tableCell_(); - sink.tableCell(); - sink.text( details.getCurrentVersion().toString() ); - sink.tableCell_(); - - sink.tableCell(); - if ( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); sink.tableCell(); - if ( newestUpdateCache.get( details, of( INCREMENTAL ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( INCREMENTAL ) ).toString() ); - safeBold_(); - } + renderIcon( upToDate ); sink.tableCell_(); - sink.tableCell(); - if ( newestUpdateCache.get( details, of( MINOR ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( MINOR ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); - - sink.tableCell(); - if ( newestUpdateCache.get( details, of( MAJOR ) ) != null ) - { - safeBold(); - sink.text( newestUpdateCache.get( details, of( MAJOR ) ).toString() ); - safeBold_(); - } - sink.tableCell_(); + renderCells( "${" + property.getName() + "}", details.getCurrentVersion() ); + renderNewestVersions( details ); sink.tableRow_(); } @@ -182,207 +125,48 @@ protected void renderPropertyDetailTable( Property property, PropertyVersions de ArtifactVersion[] allUpdates = allUpdatesCache.get( details, empty() ); boolean upToDate = allUpdates == null || allUpdates.length == 0; - final SinkEventAttributes headerAttributes = new SinkEventAttributeSet(); - headerAttributes.addAttribute( SinkEventAttributes.WIDTH, "70%" ); - final SinkEventAttributes cellAttributes = new SinkEventAttributeSet(); - headerAttributes.addAttribute( SinkEventAttributes.WIDTH, "30%" ); sink.table(); sink.tableRows( new int[] { Sink.JUSTIFY_RIGHT, Sink.JUSTIFY_LEFT }, false ); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.status" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - if ( newestUpdateCache.get( details, of( SUBINCREMENTAL ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.otherUpdatesAvailable" ) ); - } - else if ( newestUpdateCache.get( details, of( INCREMENTAL ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.incrementalUpdatesAvailable" ) ); - } - else if ( newestUpdateCache.get( details, of( MINOR ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.minorUpdatesAvailable" ) ); - } - else if ( newestUpdateCache.get( details, of( MAJOR ) ) != null ) - { - renderWarningIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.majorUpdatesAvailable" ) ); - } - else - { - renderSuccessIcon(); - sink.nonBreakingSpace(); - sink.text( getText( "report.noUpdatesAvailable" ) ); - } - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.property" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( "${" + property.getName() + "}" ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.associations" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - ArtifactAssociation[] associations = details.getAssociations(); - for ( int i = 0; i < associations.length; i++ ) - { - if ( i > 0 ) - { - sink.lineBreak(); - } - sink.text( ArtifactUtils.versionlessKey( associations[i].getArtifact() ) ); - } - sink.tableCell_(); - sink.tableRow_(); - - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.currentVersion" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( details.getCurrentVersion().toString() ); - sink.tableCell_(); - sink.tableRow_(); + renderTwoCellsRow( "report.status", () -> renderStatus( details ) ); + renderTwoCellsRow( "report.property", "${" + property.getName() + "}" ); + renderTwoCellsRow( "report.associations", () -> renderAssociations( details ) ); + renderTwoCellsRow( "report.currentVersion", details.getCurrentVersion().toString() ); if ( !upToDate ) { - Set rangeVersions = getVersionsInRange( property, details, allUpdates ); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.updateVersions" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - boolean someNotAllowed = false; - for ( int i = 0; i < allUpdates.length; i++ ) - { - if ( i > 0 ) - { - sink.lineBreak(); - } - boolean allowed = ( rangeVersions.contains( allUpdates[i].toString() ) ); - String label = getLabel( allUpdates[i], details ); - if ( !allowed ) - { - sink.text( "* " ); - someNotAllowed = true; - } - if ( allowed && label != null ) - { - safeBold(); - } - sink.text( allUpdates[i].toString() ); - if ( label != null ) - { - if ( allowed ) - { - safeBold_(); - } - sink.nonBreakingSpace(); - safeItalic(); - sink.text( label ); - safeItalic_(); - } - } - if ( someNotAllowed ) - { - sink.lineBreak(); - sink.lineBreak(); - sink.text( "* " ); - safeItalic(); - sink.text( getText( "report.excludedVersion" ) ); - safeItalic_(); - } - sink.tableCell_(); - sink.tableRow_(); + renderTwoCellsRow( "report.updateVersions", () -> renderVersions( allUpdates, details ) ); } - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.versionRange" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( StringUtils.isEmpty( property.getVersion() ) ? "[,)" : property.getVersion() ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.autoLinkDependencies" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( property.isAutoLinkDependencies() ? getText( "report.yes" ) : getText( "report.no" ) ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.banSnapshots" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( property.isBanSnapshots() ? getText( "report.yes" ) : getText( "report.no" ) ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.searchReactor" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( property.isSearchReactor() ? getText( "report.yes" ) : getText( "report.no" ) ); - sink.tableCell_(); - sink.tableRow_(); - sink.tableRow(); - sink.tableHeaderCell( headerAttributes ); - sink.text( getText( "report.preferReactor" ) ); - sink.tableHeaderCell_(); - sink.tableCell( cellAttributes ); - sink.text( property.isPreferReactor() ? getText( "report.yes" ) : getText( "report.no" ) ); - sink.tableCell_(); - sink.tableRow_(); + renderTwoCellsRow( "report.versionRange", details.getCurrentVersion().toString() ); + renderTwoCellsRow( "report.autoLinkDependencies", property.isAutoLinkDependencies() ); + renderTwoCellsRow( "report.banSnapshots", property.isBanSnapshots() ); + renderTwoCellsRow( "report.searchReactor", property.isSearchReactor() ); + renderTwoCellsRow( "report.preferReactor", property.isPreferReactor() ); sink.tableRows_(); sink.table_(); } - @SuppressWarnings( "checkstyle:MethodLength" ) - protected Set getVersionsInRange( Property property, PropertyVersions versions, - ArtifactVersion[] artifactVersions ) + /** + * Renders a row of two cells, the first cell being an header and the second cell being a non-header cell. + * @param textKey the key of the text to be rendered in the header cell. + * @param b a yes/no value to be rendered in the non-header cell. + */ + private void renderTwoCellsRow( String textKey, boolean b ) + { + renderTwoCellsRow( textKey, getText( b ? "report.yes" : "report.no" ) ); + } + + private void renderAssociations( PropertyVersions details ) { - VersionRange range; - Set rangeVersions = new HashSet<>(); - ArtifactVersion[] tmp; - if ( property.getVersion() != null ) + ArtifactAssociation[] associations = details.getAssociations(); + for ( int i = 0; i < associations.length; i++ ) { - try - { - range = VersionRange.createFromVersionSpec( property.getVersion() ); - tmp = versions.getAllUpdates( range ); - } - catch ( InvalidVersionSpecificationException e ) + if ( i > 0 ) { - tmp = artifactVersions; + sink.lineBreak(); } + sink.text( ArtifactUtils.versionlessKey( associations[i].getArtifact() ) ); } - else - { - tmp = artifactVersions; - } - for ( ArtifactVersion artifactVersion : tmp ) - { - rangeVersions.add( artifactVersion.toString() ); - } - return rangeVersions; } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java index 589cfa8a8..82472b4ee 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java @@ -20,6 +20,7 @@ * under the License. */ +import java.util.Arrays; import java.util.Locale; import org.apache.maven.artifact.versioning.ArtifactVersion; @@ -142,4 +143,86 @@ protected void safeItalic_() } } + /** + * Renders a table header containing elements denoted by the given keys + * @param keys variable argument list containing keys of the property file to retrieve the + * headers from + */ + protected void renderTableHeaderCells( String... keys ) + { + Arrays.stream( keys ) + .map( this::getText ) + .forEachOrdered( str -> + { + sink.tableHeaderCell(); + sink.text( str ); + sink.tableHeaderCell_(); + } ); + } + + /** + * Renders a bold table cell containing the given text. + * @param object the text to be rendered, or null for an empty cell. + */ + protected void renderBoldCell( Object object ) + { + renderBoldCell( true, object ); + } + /** + * Renders a table cell containing the given text. + * @param object the text to be rendered, or null for an empty cell. + */ + protected void renderCell( Object object ) + { + renderBoldCell( false, object ); + } + /** + * Renders multiple cells containing the given texts. + * @param objects the texts to be rendered, null for empty cells. + */ + protected void renderCells( Object... objects ) + { + for ( Object object : objects ) + { + renderBoldCell( false, object ); + } + } + + /** + * Renders a bold table cell containing the given text. + * @param bold true to render the cell in bold, false otherwise. + * @param object the text to be rendered, or null for an empty cell. + */ + protected void renderBoldCell( boolean bold, Object object ) + { + sink.tableCell(); + renderBoldText( bold, object ); + sink.tableCell_(); + } + + /** + * Renders a bold text. + * @param bold true to render the text in bold, false otherwise. + * @param object the text to be rendered, or null for an empty cell. + */ + protected void renderBoldText( boolean bold, Object object ) + { + if ( object != null ) + { + String text = object.toString(); + if ( !text.isEmpty() ) + { + if ( bold ) + { + safeBold(); + } + sink.text( text ); + if ( bold ) + { + safeBold_(); + } + } + } + } + } diff --git a/versions-maven-plugin/src/main/resources/dependency-updates-report.properties b/versions-maven-plugin/src/main/resources/dependency-updates-report.properties index 9b8626d4a..fb4a6e44b 100644 --- a/versions-maven-plugin/src/main/resources/dependency-updates-report.properties +++ b/versions-maven-plugin/src/main/resources/dependency-updates-report.properties @@ -53,3 +53,4 @@ report.minorUpdatesAvailable=There is at least one newer minor version available Minor updates are sometimes passive. report.majorUpdatesAvailable=There is at least one newer major version available. \ Major updates are rarely passive. +report.excludedVersion=Outside allowed version range