/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
package org.kie.workbench.common.stunner.core.validation.impl;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.kie.workbench.common.stunner.core.api.DefinitionManager;
import org.kie.workbench.common.stunner.core.diagram.Diagram;
import org.kie.workbench.common.stunner.core.graph.Element;
import org.kie.workbench.common.stunner.core.graph.Graph;
import org.kie.workbench.common.stunner.core.graph.content.definition.Definition;
import org.kie.workbench.common.stunner.core.graph.content.definition.DefinitionSet;
import org.kie.workbench.common.stunner.core.graph.processing.traverse.tree.TreeWalkTraverseProcessor;
import org.kie.workbench.common.stunner.core.rule.RuleManager;
import org.kie.workbench.common.stunner.core.rule.RuleViolation;
import org.kie.workbench.common.stunner.core.validation.DiagramElementViolation;
import org.kie.workbench.common.stunner.core.validation.DiagramValidator;
import org.kie.workbench.common.stunner.core.validation.ModelValidator;
/**
* An abstraction of the diagram validator, due to the ModelValidator (based on jsr303)
* is not available on server side yet.
*/
public abstract class AbstractDiagramValidator
implements DiagramValidator<Diagram, RuleViolation> {
private final GraphValidatorImpl graphValidator;
private final ModelValidator modelValidator;
protected AbstractDiagramValidator(final DefinitionManager definitionManager,
final RuleManager ruleManager,
final TreeWalkTraverseProcessor treeWalkTraverseProcessor,
final ModelValidator modelValidator) {
this.graphValidator = new GraphValidatorImpl(definitionManager,
ruleManager,
treeWalkTraverseProcessor);
this.modelValidator = modelValidator;
}
@Override
@SuppressWarnings("unchecked")
public void validate(final Diagram diagram,
final Consumer<Collection<DiagramElementViolation<RuleViolation>>> resultConsumer) {
final Graph graph = diagram.getGraph();
final List<DiagramElementViolation<RuleViolation>> violations = new LinkedList<>();
graphValidator.validate(graph,
Optional.empty(),
Optional.of((g, v) -> consumeBeanAndViolations(() -> violations).accept(g,
v)),
Optional.of((n, v) -> consumeBeanAndViolations(() -> violations).accept(n,
v)),
Optional.of((e, v) -> consumeBeanAndViolations(() -> violations).accept(e,
v)),
// At this point all violations have been already consumed, so no need
// to use the resulting ones here.
vs -> resultConsumer.accept(violations)
);
}
private BiConsumer<Element, Collection<RuleViolation>> consumeBeanAndViolations(final Supplier<List<DiagramElementViolation<RuleViolation>>> violations) {
return (element, ruleViolations) -> {
final Optional<Object> bean = getBean(element);
if (bean.isPresent()) {
// If the underlying bean is a Definition, it accomplishes JSR303 validations.
modelValidator.validate(bean.get(),
modelViolations -> {
violations.get().add(
ElementViolationImpl.Builder.build(element.getUUID(),
ruleViolations,
modelViolations)
);
});
} else {
// Otherwise, no need not perform bean validation.
violations.get().add(ElementViolationImpl.Builder.build(element.getUUID(),
ruleViolations));
}
};
}
private Optional<Object> getBean(final Element element) {
if (!(element.getContent() instanceof DefinitionSet) &&
element.getContent() instanceof Definition) {
return Optional.ofNullable(((Definition) element.getContent()).getDefinition());
}
return Optional.empty();
}
}