org.metaeffekt.notice.engine.NoticeParameterValidator Maven / Gradle / Ivy
/*
* Copyright 2021-2024 the original author or authors.
*
* 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.metaeffekt.notice.engine;
import com.metaeffekt.artifact.terms.model.NormalizationMetaData;
import com.metaeffekt.artifact.terms.model.TermsMetaData;
import org.metaeffekt.common.notice.model.ComponentDefinition;
import org.metaeffekt.common.notice.model.NoticeParameters;
import org.metaeffekt.notice.engine.utils.NoticeUtils;
import java.util.*;
public class NoticeParameterValidator {
private final NormalizationMetaData normalizationMetaData;
private final NoticeUtils noticeUtils;
public NoticeParameterValidator(NormalizationMetaData normalizationMetaData) {
this.normalizationMetaData = normalizationMetaData;
this.noticeUtils = new NoticeUtils(normalizationMetaData);
}
public void validateNoticeParameter(NoticeParameters noticeParameters, NoticeParameterValidationContext context) {
final ComponentDefinition mainComponent = noticeParameters.getComponent();
validateMainComponentDefinition(mainComponent, context);
validateComponentDefinition(mainComponent, context);
for (ComponentDefinition subcomponent: noticeParameters.getSubcomponents()) {
validateComponentDefinition(subcomponent, context);
}
for (ContextError contextError : context.getMessages()) {
switch (contextError.type) {
case ERROR:
context.error(contextError.message);
break;
case WARNING:
context.warn(contextError.message);
break;
case INFO:
context.info(contextError.message);
break;
}
}
}
public void validateComponentDefinition(ComponentDefinition componentDefinition, NoticeParameterValidationContext context) {
String componentDefinitionId;
if (componentDefinition == null) {
//context.error("Detected null component definition.");
return;
}
if (componentDefinition.getName() != null) {
componentDefinitionId = componentDefinition.getName();
} else {
componentDefinitionId = noticeUtils.getEffectiveLicenses(componentDefinition).toString();
}
noticeParameterStatus(componentDefinition, componentDefinitionId, context);
validateCopyrights(componentDefinition, componentDefinitionId, context);
validateNote(componentDefinition, componentDefinitionId, context);
validateVariables(componentDefinition, componentDefinitionId, context);
validateLicenses(componentDefinition, componentDefinitionId, context);
}
public void validateMainComponentDefinition(ComponentDefinition componentDefinition, NoticeParameterValidationContext context) {
if (componentDefinition == null) {
context.error("The main component is not defined! Hint: Add a main component to the notice parameter.");
} else {
if (componentDefinition.getName() == null || componentDefinition.getName().isEmpty()){
context.error("The main component needs a name! Hint: Check component name available.");
}
}
}
//Information from NoticeParameter generation
public void noticeParameterStatus(ComponentDefinition componentDefinition, String id, NoticeParameterValidationContext context) {
if (componentDefinition == null) return;
if (componentDefinition.getComponentStatus() != null && !componentDefinition.getComponentStatus().isEmpty()) {
String msg = "[Component: " + id + "]: " + componentDefinition.getComponentStatus();
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
}
}
public void validateCopyrights(ComponentDefinition componentDefinition, String id, NoticeParameterValidationContext context) {
if (componentDefinition == null) return;
for (String license : noticeUtils.getEffectiveLicenses(componentDefinition)) {
final TermsMetaData tmd = getTermsMetaData(license, context);
if (tmd.getRequiresCopyright() != null) {
if (tmd.getRequiresCopyright() && !componentDefinition.hasCopyrights()) {
if (!componentDefinition.isMissingCopyrights() || tmd.isMissingCopyrightNotAllowed()) { //null check?
if (tmd.isMissingCopyrightNotAllowed()) {
String msg = "[Component: " + id + "]: " + license + " requires copyrights. Add Copyright. Hint: This license does not allow NO copyrights. " +
"Check for default copyright sentence in license.";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
} else {
String msg = "[Component: " + id + "]: " + license + " requires copyrights. Hint: Insert " +
"copyrights or set flag \"missingCopyrights: true\" in notice parameter";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
}
}
} else if (!tmd.getRequiresCopyright() && componentDefinition.hasCopyrights()) {
String msg = "[Component: " + id + "]: " + license + " does not require copyrights, but there are copyrights " +
"present in the notice parameter. Hint: Check whether this is on purpose / Consider splitting this " +
"component to enable exact assignment of copyrights";
ContextError error = new ContextError(Type.INFO, msg);
context.getMessages().add(error);
}
} else {
if (!componentDefinition.hasCopyrights() && !componentDefinition.isMissingCopyrights()) {
String msg = "[Component: " + id + "]: No information available whether " + license + " requires copyrights. Maybe missing copyrights.";
ContextError error = new ContextError(Type.INFO, msg);
context.getMessages().add(error);
}
}
}
}
public void validateNote(ComponentDefinition componentDefinition, String id, NoticeParameterValidationContext context){
if (componentDefinition == null) return;
for (String license : noticeUtils.getEffectiveLicenses(componentDefinition)) {
final TermsMetaData termsMetaData = getTermsMetaData(license, context);
if (!componentDefinition.isNoteSet()) {
if (termsMetaData.isRequiresNote()) {
if (termsMetaData.getNoteChecklist() != null && !termsMetaData.getNoteChecklist().isEmpty()) {
StringBuilder msg = new StringBuilder("[Component: " + id + "]: " + license +
" requires a note! Please add all of the following information to the note:");
for (String todo : termsMetaData.getNoteChecklist()) {
msg.append("\n - ").append(todo);
}
ContextError error = new ContextError(Type.WARNING, msg.toString());
context.getMessages().add(error);
} else {
String msg = "[Component: " + id + "]: " + license + " requires a note! Hint: Add a note (no checklist available).";
ContextError error = new ContextError(Type.WARNING, msg);
context.getMessages().add(error);
}
}
}
if (componentDefinition.isNoteSet() && componentDefinition.getNote().isEmpty()){
String msg = "[Component: " + id + "]: Empty note specified. Hint: Check whether note is required.";
ContextError error = new ContextError(Type.WARNING, msg);
context.getMessages().add(error);
}
}
}
private void validateVariables(ComponentDefinition componentDefinition, String id, NoticeParameterValidationContext context) {
if (componentDefinition == null) return;
int licensesWithVariables = 0;
for (String effectiveLicense : noticeUtils.getEffectiveLicenses(componentDefinition)) {
TermsMetaData tmd = getTermsMetaData(effectiveLicense, context);
if (tmd.getLicenseTemplate() != null && tmd.getLicenseTemplate().contains("{{")) {
if (componentDefinition.getVariables() == null) {
String msg = "[Component: " + id + "]: Provide variable set for " + effectiveLicense + ".";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
}
licensesWithVariables++;
}
}
if (componentDefinition.getVariables() == null) return;
if (licensesWithVariables == 0) {
String msg = "[Component: " + id + "]: None of the licenses in this component requires variables, but variables are specified. Hint: Check whether license is missing or variables are obsolete.";
ContextError error = new ContextError(Type.WARNING, msg);
context.getMessages().add(error);
} else if (licensesWithVariables == 1) {
//check if they match
for (String effectiveLicense : noticeUtils.getEffectiveLicenses(componentDefinition)) {
TermsMetaData tmd = getTermsMetaData(effectiveLicense, context);
if (tmd.getLicenseTemplate() != null && tmd.getLicenseTemplate().contains("{{")) {
String licenseTemplate = tmd.getLicenseTemplate();
for (Map.Entry entry : componentDefinition.getVariables().entrySet()) {
String key = "{{" + entry.getKey() + "}}";
if (licenseTemplate.contains(key)) {
licenseTemplate = licenseTemplate.replace(key, "");
} else {
String msg = "[Component: " + id + "]: Wrong variable specified. " + key + "is wrong.";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
}
}
if (licenseTemplate.matches(".*\\{\\{([^\\}]+)}}.*")) {
String msg = "[Component: " + id + "]: There are still un-replaced variables in the notice Parameter";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
}
}
}
} else if (licensesWithVariables > 1) {
String msg = "[Component: " + id + "]: At least two of the licenses in this component require variables, but only one variable set is specified. Hint: Split into subcomponents and add variable set.";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
}
if (componentDefinition.getVariables().containsValue("")) {
String msg = "[Component: " + id + "]: At least one variable in component has empty content. Provide Variable content";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
}
}
public void validateLicenses(ComponentDefinition componentDefinition, String id, NoticeParameterValidationContext context) {
if(componentDefinition == null) return;
for (String effectiveLicense : noticeUtils.getEffectiveLicenses(componentDefinition)) {
// FIXME: use structured data isUnspecific
if (effectiveLicense.contains("undefined")) {
String msg = "[Component: " + id + "]: " + effectiveLicense + " is not appropriate as effective license.";
ContextError error = new ContextError(Type.WARNING, msg);
context.getMessages().add(error);
}
}
// NOTE: not enforcing any effective license rules here. Effective licenses may be determined using a customer
// rule set.
}
public TermsMetaData getTermsMetaData(String license, NoticeParameterValidationContext context) {
final TermsMetaData termsMetaData = normalizationMetaData.resolveTermsMetaData(license);
if (termsMetaData == null) {
String msg = "No terms metadata for " + license + "! Hint: Isolate and provide license text to be added to metadata.";
ContextError error = new ContextError(Type.ERROR, msg);
context.getMessages().add(error);
return NoticeUtils.createDefaultTermsMetaData(license);
} else {
return termsMetaData;
}
}
public enum Type {
WARNING,
ERROR,
INFO
}
public class ContextError {
Type type;
String message;
public ContextError(Type type, String message) {
this.type = type;
this.message = message;
}
public void addError(NoticeParameterValidationContext context) {
context.getMessages().add(this);
}
@Override
public int hashCode() {
return Objects.hash(type, message);
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (o instanceof ContextError) {
ContextError toCompare = (ContextError) o;
if (!Objects.equals(toCompare.type, this.type)) {
return false;
}
if (!Objects.equals(toCompare.message, this.message)) {
return false;
}
} else {
return false;
}
return true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy