-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#408 added initial implementation for BaselineManager
- Loading branch information
1 parent
d39c791
commit 5fdc4b5
Showing
13 changed files
with
728 additions
and
88 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
...analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/baseline/Baseline.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.buschmais.jqassistant.core.analysis.api.baseline; | ||
|
||
import java.util.SortedMap; | ||
import java.util.TreeMap; | ||
|
||
import lombok.Getter; | ||
import lombok.ToString; | ||
|
||
/** | ||
* Represents a baseline for analyze results. | ||
* <p> | ||
* Note that the data structures rely on {@link SortedMap}s to preserve the order of entries. This is required for creating diffs between baseline files which are generated from these structures. | ||
*/ | ||
@Getter | ||
@ToString | ||
public class Baseline { | ||
|
||
/** | ||
* The baseline per {@link com.buschmais.jqassistant.core.rule.api.model.Concept} id. | ||
*/ | ||
private SortedMap<String, RuleBaseline> concepts = new TreeMap<>(); | ||
|
||
/** | ||
* The baseline per {@link com.buschmais.jqassistant.core.rule.api.model.Constraint} id. | ||
*/ | ||
private SortedMap<String, RuleBaseline> constraints = new TreeMap<>(); | ||
|
||
/** | ||
* Represent a baseline for a specific {@link com.buschmais.jqassistant.core.rule.api.model.Concept} or {@link com.buschmais.jqassistant.core.rule.api.model.Constraint}. | ||
*/ | ||
@Getter | ||
@ToString | ||
public static class RuleBaseline { | ||
|
||
/** | ||
* Holds the row key as key and the columns (as human-readable labels) as values. | ||
*/ | ||
private final SortedMap<String, SortedMap<String, String>> rows = new TreeMap<>(); | ||
|
||
} | ||
|
||
} |
81 changes: 81 additions & 0 deletions
81
...s/src/main/java/com/buschmais/jqassistant/core/analysis/api/baseline/BaselineManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package com.buschmais.jqassistant.core.analysis.api.baseline; | ||
|
||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.SortedMap; | ||
import java.util.TreeMap; | ||
|
||
import com.buschmais.jqassistant.core.report.api.model.Column; | ||
import com.buschmais.jqassistant.core.report.api.model.Row; | ||
import com.buschmais.jqassistant.core.rule.api.model.Concept; | ||
import com.buschmais.jqassistant.core.rule.api.model.Constraint; | ||
import com.buschmais.jqassistant.core.rule.api.model.ExecutableRule; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
/** | ||
* Verifies result rows gathered for rule during an analyze task against a baseline | ||
* <p> | ||
* {@link Row}s of a constraint are considered as "new" if | ||
* <ul> | ||
* <li>No baseline exists.</li> | ||
* <li>A baseline exists but does not yet contain the {@link Row}.</li> | ||
* </ul> | ||
* <p> | ||
* Only {@link Row}s that have been validated using {@link #isNew(ExecutableRule, Row)} ({@link ExecutableRule}, Row)} are copied to the new baseline. | ||
* <p> | ||
*/ | ||
@RequiredArgsConstructor | ||
public class BaselineManager { | ||
|
||
private final com.buschmais.jqassistant.core.analysis.api.configuration.Baseline configuration; | ||
|
||
private final Optional<Baseline> optionalOldBaseline; | ||
|
||
private final Baseline newBaseline = new Baseline(); | ||
|
||
public boolean isNew(ExecutableRule<?> executableRule, Row row) { | ||
String ruleId = executableRule.getId(); | ||
String rowKey = row.getKey(); | ||
Map<String, Column<?>> columns = row.getColumns(); | ||
return optionalOldBaseline.map(oldBaseline -> { | ||
SortedMap<String, Baseline.RuleBaseline> ruleBaseline = getRows(oldBaseline, executableRule); | ||
Baseline.RuleBaseline oldRuleBaseline = ruleBaseline.get(ruleId); | ||
if (oldRuleBaseline != null && oldRuleBaseline.getRows() | ||
.containsKey(rowKey)) { | ||
add(ruleId, rowKey, columns); | ||
return false; | ||
} | ||
return true; | ||
}) | ||
.orElseGet(() -> { | ||
add(ruleId, rowKey, columns); | ||
return true; | ||
}); | ||
} | ||
|
||
private static SortedMap<String, Baseline.RuleBaseline> getRows(Baseline baseline, ExecutableRule<?> executableRule) { | ||
if (executableRule instanceof Concept) { | ||
return baseline.getConcepts(); | ||
} else if (executableRule instanceof Constraint) { | ||
return baseline.getConstraints(); | ||
} | ||
throw new IllegalArgumentException("Unsupported executable rule: " + executableRule); | ||
} | ||
|
||
private void add(String constraintId, String rowKey, Map<String, Column<?>> columns) { | ||
Baseline.RuleBaseline newRuleBaseline = newBaseline.getConstraints() | ||
.computeIfAbsent(constraintId, key -> new Baseline.RuleBaseline()); | ||
TreeMap<String, String> row = new TreeMap<>(); | ||
columns.entrySet() | ||
.stream() | ||
.forEach(entry -> row.put(entry.getKey(), entry.getValue() | ||
.getLabel())); | ||
newRuleBaseline.getRows() | ||
.put(rowKey, row); | ||
} | ||
|
||
public Baseline getNewBaseline() { | ||
return newBaseline; | ||
} | ||
} |
115 changes: 115 additions & 0 deletions
115
...rc/main/java/com/buschmais/jqassistant/core/analysis/api/baseline/BaselineRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package com.buschmais.jqassistant.core.analysis.api.baseline; | ||
|
||
import java.io.*; | ||
import java.util.*; | ||
|
||
import com.buschmais.jqassistant.core.shared.xml.JAXBHelper; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.jqassistant.schema.baseline.v2.ColumnType; | ||
import org.jqassistant.schema.baseline.v2.JqassistantBaseline; | ||
import org.jqassistant.schema.baseline.v2.RowType; | ||
import org.jqassistant.schema.baseline.v2.RuleType; | ||
|
||
import static java.util.Optional.empty; | ||
import static java.util.Optional.of; | ||
|
||
@RequiredArgsConstructor | ||
public class BaselineRepository { | ||
|
||
private static final JAXBHelper<JqassistantBaseline> JAXB_HELPER = new JAXBHelper<>(JqassistantBaseline.class); | ||
|
||
private final com.buschmais.jqassistant.core.analysis.api.configuration.Baseline configuration; | ||
|
||
private final File ruleDirectory; | ||
|
||
public Optional<Baseline> read() { | ||
File baselineFile = getFile(); | ||
if (baselineFile.exists()) { | ||
return of(read(baselineFile)); | ||
} | ||
return empty(); | ||
} | ||
|
||
public void write(Baseline baseline) { | ||
write(baseline, getFile()); | ||
} | ||
|
||
private File getFile() { | ||
return configuration.file() | ||
.map(File::new) | ||
.orElse(new File(ruleDirectory, "jqassistant-baseline.xml")); | ||
} | ||
|
||
private static Baseline read(File baselineFile) { | ||
try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(baselineFile))) { | ||
return toBaseline(JAXB_HELPER.unmarshal(inputStream)); | ||
} catch (IOException e) { | ||
throw new IllegalStateException("Unable to read baseline file " + baselineFile, e); | ||
} | ||
} | ||
|
||
private static Baseline toBaseline(JqassistantBaseline jqassistantBaseline) { | ||
Baseline baseline = new Baseline(); | ||
toBaseline(jqassistantBaseline.getConstraint(), baseline.getConstraints()); | ||
toBaseline(jqassistantBaseline.getConcept(), baseline.getConcepts()); | ||
return baseline; | ||
} | ||
|
||
private static void toBaseline(List<RuleType> ruleTypes, SortedMap<String, Baseline.RuleBaseline> ruleBaselines) { | ||
for (RuleType ruleType : ruleTypes) { | ||
Baseline.RuleBaseline ruleBaseline = new Baseline.RuleBaseline(); | ||
for (RowType rowType : ruleType.getRow()) { | ||
SortedMap<String, String> columns = new TreeMap<>(); | ||
for (ColumnType columnType : rowType.getColumn()) { | ||
columns.put(columnType.getName(), columnType.getValue()); | ||
} | ||
ruleBaseline.getRows() | ||
.put(rowType.getKey(), columns); | ||
} | ||
ruleBaselines.put(ruleType.getId(), ruleBaseline); | ||
} | ||
} | ||
|
||
private static void write(Baseline baseline, File baselinefile) { | ||
JqassistantBaseline jqassistantBaseline = fromBaseline(baseline); | ||
try { | ||
JAXB_HELPER.marshal(jqassistantBaseline, new FileOutputStream(baselinefile)); | ||
} catch (IOException e) { | ||
throw new IllegalStateException("Unable to write baseline file " + baselinefile, e); | ||
} | ||
} | ||
|
||
private static JqassistantBaseline fromBaseline(Baseline baseline) { | ||
JqassistantBaseline jqassistantBaseline = new JqassistantBaseline(); | ||
fromBaseline(baseline.getConstraints(), jqassistantBaseline.getConstraint()); | ||
fromBaseline(baseline.getConcepts(), jqassistantBaseline.getConcept()); | ||
return jqassistantBaseline; | ||
} | ||
|
||
private static void fromBaseline(SortedMap<String, Baseline.RuleBaseline> ruleBaselines, List<RuleType> ruleTypes) { | ||
for (Map.Entry<String, Baseline.RuleBaseline> ruleBaselineEntry : ruleBaselines.entrySet()) { | ||
String ruleId = ruleBaselineEntry.getKey(); | ||
Baseline.RuleBaseline ruleBaseline = ruleBaselineEntry.getValue(); | ||
RuleType ruleType = new RuleType(); | ||
ruleType.setId(ruleId); | ||
for (Map.Entry<String, SortedMap<String, String>> rowEntry : ruleBaseline.getRows() | ||
.entrySet()) { | ||
String rowKey = rowEntry.getKey(); | ||
SortedMap<String, String> columns = rowEntry.getValue(); | ||
RowType rowType = new RowType(); | ||
rowType.setKey(rowKey); | ||
for (Map.Entry<String, String> columnEntry : columns.entrySet()) { | ||
ColumnType columnType = new ColumnType(); | ||
columnType.setName(columnEntry.getKey()); | ||
columnType.setValue(columnEntry.getValue()); | ||
rowType.getColumn() | ||
.add(columnType); | ||
} | ||
ruleType.getRow() | ||
.add(rowType); | ||
ruleTypes.add(ruleType); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
...sis/src/main/java/com/buschmais/jqassistant/core/analysis/api/configuration/Baseline.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.buschmais.jqassistant.core.analysis.api.configuration; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
import com.buschmais.jqassistant.core.shared.annotation.Description; | ||
|
||
import io.smallrye.config.ConfigMapping; | ||
import io.smallrye.config.WithDefault; | ||
|
||
@ConfigMapping(prefix = "jqassistant.analyze.baseline") | ||
public interface Baseline { | ||
|
||
@WithDefault("false") | ||
boolean enabled(); | ||
|
||
String FILE = "file"; | ||
|
||
@Description("The name of the file for reading and writing the baseline.") | ||
Optional<String> file(); | ||
|
||
String INCLUDE_CONCEPTS = "include-concepts"; | ||
|
||
@Description("The concepts to be included.") | ||
Optional<List<String>> includeConcepts(); | ||
|
||
String INCLUDE_CONSTRAINTS = "include-constraints"; | ||
|
||
@Description("The constraints to be included.") | ||
@WithDefault("*") | ||
List<String> includeConstraints(); | ||
|
||
} |
Oops, something went wrong.