/*
* #%L
* Nazgul Project: nazgul-core-quickstart-api
* %%
* Copyright (C) 2010 - 2017 jGuru Europe AB
* %%
* Licensed under the jGuru Europe AB license (the "License"), based
* on Apache License, Version 2.0; you may not use this file except
* in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*
*/
package se.jguru.nazgul.core.quickstart.api.analyzer;
import org.apache.commons.lang3.Validate;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import se.jguru.nazgul.core.quickstart.api.InvalidStructureException;
import se.jguru.nazgul.core.quickstart.api.analyzer.patterns.DefaultProjectParentPatterns;
import se.jguru.nazgul.core.quickstart.api.analyzer.patterns.DefaultTopReactorPatterns;
import se.jguru.nazgul.core.quickstart.api.analyzer.patterns.MavenModelPatterns;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* PomAnalyzer implementation which uses a set of regular expressions to validate
* that the topmost reactor and parent POMs are valid.
*
* @author <a href="mailto:lj@jguru.se">Lennart Jörelid</a>, jGuru Europe AB
*/
public class PatternPomAnalyzer extends AbstractPomAnalyzer {
// Internal state
private MavenModelPatterns parentPomPatterns;
private MavenModelPatterns topReactorPomPatterns;
/**
* Convenience constructor creating a new PatternPomAnalyzer using the supplied NamingStrategy and
* using the DefaultTopReactorPatterns and DefaultProjectParentPatterns MavenModelPatterns
* implementations.
*
* @param namingStrategy A non-null NamingStrategy used to validate Models.
*/
public PatternPomAnalyzer(final NamingStrategy namingStrategy) {
this(namingStrategy, new DefaultProjectParentPatterns(), new DefaultTopReactorPatterns());
}
/**
* Creates a new PatternPomAnalyzer instance wrapping the supplied NamingStrategy and MavenModelPatterns.
*
* @param namingStrategy A non-null NamingStrategy used to validate Models.
* @param parentPomPatterns A non-null MavenModelPatterns definition for identifying the topmost Parent POM
* within a multi-module reactor.
* @param topReactorPomPatterns A non-null MavenModelPatterns definition for identifying the top Reactor POM
* within a multi-module reactor.
*/
public PatternPomAnalyzer(final NamingStrategy namingStrategy,
final MavenModelPatterns parentPomPatterns,
final MavenModelPatterns topReactorPomPatterns) {
super(namingStrategy);
Validate.notNull(parentPomPatterns, "Cannot handle null parentPomPatterns argument.");
Validate.notNull(topReactorPomPatterns, "Cannot handle null topReactorPomPatterns argument.");
this.parentPomPatterns = parentPomPatterns;
this.topReactorPomPatterns = topReactorPomPatterns;
}
/**
* {@inheritDoc}
*/
@Override
protected void performCustomRootReactorPomValidation(final Model rootReactorModel)
throws InvalidStructureException {
validatePomPatterns(rootReactorModel, topReactorPomPatterns);
}
/**
* {@inheritDoc}
*/
@Override
protected void performCustomTopmostParentPomValidation(final Model topmostParentModel)
throws InvalidStructureException {
validatePomPatterns(topmostParentModel, parentPomPatterns);
}
//
// Private helpers
//
private void validatePomPatterns(final Model model, final MavenModelPatterns patterns) {
final Parent parent = model.getParent();
final String groupId = model.getGroupId();
final String artifactId = model.getArtifactId();
String suffix = "for POM (" + groupId + "/" + artifactId;
if (parent == null) {
throw new InvalidStructureException("Missing Parent definition " + suffix + ")");
}
final String effectiveVersion = model.getVersion() == null
? parent.getVersion()
: model.getVersion();
suffix = suffix + "/" + effectiveVersion + ")";
final boolean isNullValid = patterns.nullPatternImpliesValid();
final boolean groupIdMatch = isMatch(patterns.getGroupIdPattern(), isNullValid, groupId);
final boolean artifactIdMatch = isMatch(patterns.getArtifactIdPattern(), isNullValid, artifactId);
final boolean parentGroupIdMatch = isMatch(
patterns.getParentGroupIdPattern(), isNullValid, parent.getGroupId());
final boolean parentArtifactIdMatch = isMatch(
patterns.getParentArtifactIdPattern(), isNullValid, parent.getArtifactId());
final List<String> errors = new ArrayList<>();
if (!parentGroupIdMatch) {
errors.add("Incorrect parent groupId [" + parent.getGroupId() + "]");
}
if (!parentArtifactIdMatch) {
errors.add("Incorrect parent artifactId [" + parent.getArtifactId() + "]");
}
if (!groupIdMatch) {
errors.add("Incorrect groupId [" + groupId + "]");
}
if (!artifactIdMatch) {
errors.add("Incorrect artifactId [" + artifactId + "]");
}
if (errors.size() > 0) {
StringBuilder builder = new StringBuilder("Invalid structure detected for POM ("
+ model.getGroupId() + "/" + model.getArtifactId() + "/" + effectiveVersion + "): ");
for (int i = 0; i < errors.size(); i++) {
builder.append("\n " + (i + 1) + ": " + errors.get(i));
}
throw new InvalidStructureException(builder.toString());
}
}
private boolean isMatch(final Pattern aPattern, final boolean nullImpliesValid, final String toMatch) {
// Should we compare nulls?
if (aPattern == null || toMatch == null) {
return nullImpliesValid;
}
return aPattern.matcher(toMatch).matches();
}
}