diff --git a/src/main/java/org/jpeek/App.java b/src/main/java/org/jpeek/App.java index 116c2bf1..c1180e83 100644 --- a/src/main/java/org/jpeek/App.java +++ b/src/main/java/org/jpeek/App.java @@ -169,112 +169,112 @@ public void analyze() throws IOException { if (this.params.containsKey("LCOM")) { reports.add( new XslReport( - chain.transform(skeleton), - "LCOM", this.params, xsl, 10.0d, -5.0d + chain.transform(skeleton), xsl, + new ReportData("LCOM", this.params, 10.0d, -5.0d) ) ); } if (this.params.containsKey("CAMC")) { reports.add( new XslReport( - chain.transform(skeleton), - "CAMC", this.params, xsl + chain.transform(skeleton), xsl, + new ReportData("CAMC", this.params) ) ); } if (this.params.containsKey("MMAC")) { reports.add( new XslReport( - chain.transform(skeleton), - "MMAC", this.params, xsl, 0.5d, 0.1d + chain.transform(skeleton), xsl, + new ReportData("MMAC", this.params, 0.5d, 0.1d) ) ); } if (this.params.containsKey("LCOM5")) { reports.add( new XslReport( - chain.transform(skeleton), - "LCOM5", this.params, xsl, 0.5d, -0.1d + chain.transform(skeleton), xsl, + new ReportData("LCOM5", this.params, 0.5d, -0.1d) ) ); } if (this.params.containsKey("NHD")) { reports.add( new XslReport( - chain.transform(skeleton), - "NHD", xsl + chain.transform(skeleton), xsl, + new ReportData("NHD") ) ); } if (this.params.containsKey("LCOM2")) { reports.add( new XslReport( - chain.transform(skeleton), - "LCOM2", this.params, xsl + chain.transform(skeleton), xsl, + new ReportData("LCOM2", this.params) ) ); } if (this.params.containsKey("LCOM3")) { reports.add( new XslReport( - chain.transform(skeleton), - "LCOM3", this.params, xsl + chain.transform(skeleton), xsl, + new ReportData("LCOM3", this.params) ) ); } if (this.params.containsKey("SCOM")) { reports.add( new XslReport( - chain.transform(skeleton), - "SCOM", this.params, xsl + chain.transform(skeleton), xsl, + new ReportData("SCOM", this.params) ) ); } if (this.params.containsKey("OCC")) { reports.add( new XslReport( - chain.transform(skeleton), - "OCC", this.params, xsl + chain.transform(skeleton), xsl, + new ReportData("OCC", this.params) ) ); } if (this.params.containsKey("PCC")) { reports.add( new XslReport( - chain.transform(skeleton), - "PCC", xsl + chain.transform(skeleton), xsl, + new ReportData("PCC") ) ); } if (this.params.containsKey("TCC")) { reports.add( new XslReport( - chain.transform(skeleton), - "TCC", xsl + chain.transform(skeleton), xsl, + new ReportData("TCC") ) ); } if (this.params.containsKey("LCC")) { reports.add( new XslReport( - chain.transform(skeleton), - "LCC", xsl + chain.transform(skeleton), xsl, + new ReportData("LCC") ) ); } if (this.params.containsKey("CCM")) { reports.add( new XslReport( - chain.transform(skeleton), - "CCM", xsl + chain.transform(skeleton), xsl, + new ReportData("CCM") ) ); } if (this.params.containsKey("MWE")) { reports.add( new XslReport( - chain.transform(skeleton), - "MWE", xsl + chain.transform(skeleton), xsl, + new ReportData("MWE") ) ); } diff --git a/src/main/java/org/jpeek/ReportData.java b/src/main/java/org/jpeek/ReportData.java new file mode 100644 index 00000000..75a0ba1d --- /dev/null +++ b/src/main/java/org/jpeek/ReportData.java @@ -0,0 +1,134 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017-2019 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.jpeek; + +import java.util.HashMap; +import java.util.Map; +import org.cactoos.map.MapOf; + +/** + * Report data holder. + * + * @since 0.30.9 + */ +final class ReportData { + /** + * Default mean. + */ + private static final double DEFAULT_MEAN = 0.5d; + + /** + * Default sigma. + */ + private static final double DEFAULT_SIGMA = 0.1d; + + /** + * The metric. + */ + private final String metr; + + /** + * Mean. + */ + private final double man; + + /** + * Sigma. + */ + private final double sig; + + /** + * XSL params. + */ + private final Map args; + + /** + * Ctor. + * @param name Name of the metric + */ + ReportData(final String name) { + this( + name, new HashMap<>(0), ReportData.DEFAULT_MEAN, ReportData.DEFAULT_SIGMA + ); + } + + /** + * Ctor. + * @param name Name of metric + * @param args Params for XSL + */ + ReportData(final String name, final Map args) { + this( + name, args, ReportData.DEFAULT_MEAN, ReportData.DEFAULT_SIGMA + ); + } + + /** + * Ctor. + * @param name Name of the metric + * @param args Params for XSL + * @param mean Mean + * @param sigma Sigma + * @checkstyle ParameterNumberCheck (10 lines) + */ + ReportData(final String name, final Map args, final double mean, + final double sigma) { + this.metr = name; + this.args = new MapOf(new HashMap<>(args)); + this.man = mean; + this.sig = sigma; + } + + /** + * Metric name accessor. + * @return The metric + */ + public String metric() { + return this.metr; + } + + /** + * Mean accessor. + * @return The mean + */ + public double mean() { + return this.man; + } + + /** + * Sigma accessor. + * @return Sigma + */ + public double sigma() { + return this.sig; + } + + /** + * Params accessor. + * @return Params + */ + public Map params() { + return this.args; + } +} diff --git a/src/main/java/org/jpeek/XslReport.java b/src/main/java/org/jpeek/XslReport.java index 5dea6d2a..abac22fd 100644 --- a/src/main/java/org/jpeek/XslReport.java +++ b/src/main/java/org/jpeek/XslReport.java @@ -35,7 +35,6 @@ import com.jcabi.xml.XSLDocument; import java.io.IOException; import java.nio.file.Path; -import java.util.HashMap; import java.util.Map; import org.cactoos.collection.CollectionOf; import org.cactoos.io.TeeInput; @@ -52,15 +51,6 @@ * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) */ final class XslReport implements Report { - /** - * Default mean. - */ - private static final double DEFAULT_MEAN = 0.5d; - - /** - * Default sigma. - */ - private static final double DEFAULT_SIGMA = 0.1d; /** * Location to the schema file. @@ -81,6 +71,11 @@ final class XslReport implements Report { XslReport.class.getResourceAsStream("xsl/metric.xsl") ).with(new ClasspathSources()); + /** + * XSL params. + */ + private final Map params; + /** * The skeleton. */ @@ -101,62 +96,17 @@ final class XslReport implements Report { */ private final XSL post; - /** - * XSL params. - */ - private final Map params; - - /** - * Ctor. - * @param xml Skeleton - * @param name Name of the metric - * @param calc Calculus - */ - XslReport(final XML xml, final String name, final Calculus calc) { - this( - xml, name, new HashMap<>(0), calc, - XslReport.DEFAULT_MEAN, XslReport.DEFAULT_SIGMA - ); - } - - /** - * Ctor. - * @param xml Skeleton - * @param name Name of metric - * @param args Params for XSL - * @param calc Calculus - * @checkstyle ParameterNumberCheck (5 lines) - */ - XslReport(final XML xml, final String name, final Map args, - final Calculus calc) { - this( - xml, name, args, calc, - XslReport.DEFAULT_MEAN, XslReport.DEFAULT_SIGMA - ); - } - /** * Ctor. * @param xml Skeleton - * @param name Name of the metric - * @param args Params for XSL * @param calc Calculus - * @param mean Mean - * @param sigma Sigma - * @todo #390:30min this constructor now has too many arguments. We should find a way - * to refactor the constructor or the class to have fewer parameters. - * We could start by analyzing the usage of this.params (args in this - * constructor) and get rid of it if it is not used. - * Another idea could be to have a data class contaning reporting params: - * name, args, mean, sigma. + * @param data Report data * @checkstyle ParameterNumberCheck (10 lines) */ - XslReport(final XML xml, final String name, - final Map args, final Calculus calc, - final double mean, final double sigma) { + XslReport(final XML xml, final Calculus calc, final ReportData data) { this.skeleton = xml; - this.metric = name; - this.params = args; + this.metric = data.metric(); + this.params = data.params(); this.calculus = calc; this.post = new XSLChain( new CollectionOf<>( @@ -164,7 +114,8 @@ final class XslReport implements Report { XslReport.class.getResourceAsStream( "xsl/metric-post-colors.xsl" ) - ).with("low", mean - sigma).with("high", mean + sigma), + ).with("low", data.mean() - data.sigma()) + .with("high", data.mean() + data.sigma()), new XSLDocument( XslReport.class.getResourceAsStream( "xsl/metric-post-range.xsl" diff --git a/src/test/java/org/jpeek/MetricsTest.java b/src/test/java/org/jpeek/MetricsTest.java index 92bd72ff..e26d6692 100644 --- a/src/test/java/org/jpeek/MetricsTest.java +++ b/src/test/java/org/jpeek/MetricsTest.java @@ -50,6 +50,7 @@ * to fix puzzles in LCC.xml. * @checkstyle JavadocTagsCheck (500 lines) * @checkstyle JavadocMethodCheck (500 lines) + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) */ public final class MetricsTest { @@ -59,8 +60,8 @@ public void testsTarget(final String target, final String metric, final double v throws Exception { final Path output = Files.createTempDirectory(""); new XslReport( - new Skeleton(new FakeBase(target)).xml(), - metric, new XslCalculus() + new Skeleton(new FakeBase(target)).xml(), new XslCalculus(), + new ReportData(metric) ).save(output); final String xpath; if (Double.isNaN(value)) { diff --git a/src/test/java/org/jpeek/ReportDataTest.java b/src/test/java/org/jpeek/ReportDataTest.java new file mode 100644 index 00000000..c550abb7 --- /dev/null +++ b/src/test/java/org/jpeek/ReportDataTest.java @@ -0,0 +1,123 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017-2019 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.jpeek; + +import java.util.HashMap; +import java.util.Map; +import org.cactoos.map.MapEntry; +import org.cactoos.map.MapOf; +import org.hamcrest.core.IsEqual; +import org.junit.jupiter.api.Test; +import org.llorllale.cactoos.matchers.Assertion; +import org.llorllale.cactoos.matchers.HasValues; +import org.llorllale.cactoos.matchers.Throws; + +/** + * Tests for {@link ReportData}. + * @since 0.30.9 + */ +public final class ReportDataTest { + + @Test + public void reportsName() throws Exception { + final String name = "whatever"; + final ReportData data = new ReportData(name); + new Assertion<>( + "Must returns name", + data.metric(), + new IsEqual<>(name) + ).affirm(); + } + + @Test + public void reportsMean() throws Exception { + final String name = "whats"; + final double mean = 0; + final double sigma = 1; + final ReportData data = new ReportData(name, ReportDataTest.args(), mean, sigma); + new Assertion<>( + "Must returns mean", + data.mean(), + new IsEqual<>(mean) + ).affirm(); + } + + @Test + public void reportsSigma() throws Exception { + final String name = "whatevermetric"; + final double mean = 0; + final double sigma = 1; + final ReportData data = new ReportData(name, ReportDataTest.args(), mean, sigma); + new Assertion<>( + "Must returns sigma", + data.sigma(), + new IsEqual<>(sigma) + ).affirm(); + } + + @Test + public void reportsParams() throws Exception { + final String name = "name"; + final Map sample = ReportDataTest.args(); + final ReportData data = new ReportData(name, sample); + new Assertion<>( + "Must returns args", + data.params().entrySet(), + new HasValues<>(sample.entrySet()) + ).affirm(); + } + + @Test + public void shouldBeImmutableWhenModifyingPassedParams() throws Exception { + final String name = "metric"; + final Map sample = ReportDataTest.args(); + final Map params = new HashMap<>(sample); + final ReportData data = new ReportData(name, params); + params.clear(); + new Assertion<>( + "Must be immutable", + data.params().entrySet().size(), + new IsEqual<>(sample.size()) + ).affirm(); + } + + @Test + public void throwsExceptionWhenTryingToModifyParams() throws Exception { + final String name = "metrics"; + final ReportData data = new ReportData(name, new HashMap<>(ReportDataTest.args())); + new Assertion<>( + "Must throw an exception if retrieved is modified", + () -> { + data.params().clear(); + return ""; + }, new Throws<>(UnsupportedOperationException.class) + ).affirm(); + } + + private static Map args() { + return new MapOf( + new MapEntry<>("a", 1), new MapEntry<>("b", 2) + ); + } +} diff --git a/src/test/java/org/jpeek/XslReportTest.java b/src/test/java/org/jpeek/XslReportTest.java index 9c8991a1..0298d49f 100644 --- a/src/test/java/org/jpeek/XslReportTest.java +++ b/src/test/java/org/jpeek/XslReportTest.java @@ -49,7 +49,7 @@ public final class XslReportTest { public void createsXmlReport() throws IOException { final Path output = Files.createTempDirectory(""); new XslReport( - new Skeleton(new FakeBase()).xml(), "LCOM", new XslCalculus() + new Skeleton(new FakeBase()).xml(), new XslCalculus(), new ReportData("LCOM") ).save(output); new Assertion<>( "Must LCOM.xml file exists", @@ -72,8 +72,7 @@ public void createsXmlReportWithXpaths() throws IOException { "NoMethods", "Bar", "OverloadMethods", "OnlyOneMethodWithParams", "WithoutAttributes" ) - ).xml(), - "LCOM", new XslCalculus() + ).xml(), new XslCalculus(), new ReportData("LCOM") ).save(output); new Assertion<>( "Must create LCOM report", @@ -91,7 +90,7 @@ public void createsXmlReportWithXpaths() throws IOException { public void createsXmlReportWithEmptyProject() throws IOException { final Path output = Files.createTempDirectory(""); new XslReport( - new Skeleton(new FakeBase()).xml(), "LCOM", new XslCalculus() + new Skeleton(new FakeBase()).xml(), new XslCalculus(), new ReportData("LCOM") ).save(output); new Assertion<>( "Report for empty project created", @@ -121,8 +120,7 @@ public void createsFullXmlReport() throws IOException { .add("class").attr("id", "D").attr("value", "0.7").up() .add("class").attr("id", "E").attr("value", "NaN").up() ).xmlQuietly() - ), - "LCOM", new XslCalculus() + ), new XslCalculus(), new ReportData("LCOM") ).save(output); new Assertion<>( "Must create full report", @@ -145,7 +143,7 @@ public void createsFullXmlReport() throws IOException { public void setsCorrectSchemaLocation() throws IOException { final Path output = Files.createTempDirectory(""); new XslReport( - new Skeleton(new FakeBase()).xml(), "LCOM", new XslCalculus() + new Skeleton(new FakeBase()).xml(), new XslCalculus(), new ReportData("LCOM") ).save(output); new Assertion<>( "Must have correct schema location",