/**
* Copyright © 2002 Instituto Superior Técnico
*
* This file is part of FenixEdu Academic.
*
* FenixEdu Academic is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FenixEdu Academic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.academic.domain.curricularRules.executors;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.fenixedu.academic.domain.curricularRules.executors.ruleExecutors.EnrolmentResultType;
import org.fenixedu.academic.domain.degreeStructure.DegreeModule;
import org.fenixedu.academic.domain.exceptions.DomainException;
public class RuleResult {
private RuleResultType result;
private Set<RuleResultMessage> messages;
private Map<DegreeModule, EnrolmentResultType> enrolmentResultTypeByDegreeModule;
private RuleResult() {
this.enrolmentResultTypeByDegreeModule = new HashMap<DegreeModule, EnrolmentResultType>();
this.messages = new HashSet<RuleResultMessage>();
}
private RuleResult(final RuleResultType resultType,
final Map<DegreeModule, EnrolmentResultType> enrolmentResultTypeByDegreeModule, final Set<RuleResultMessage> messages) {
this();
this.result = resultType;
this.enrolmentResultTypeByDegreeModule = enrolmentResultTypeByDegreeModule;
this.messages = messages;
}
private RuleResult(final RuleResultType result, final EnrolmentResultType enrolmentResultType, final DegreeModule degreeModule) {
this();
if (result == null) {
throw new DomainException("error.curricularRules.executors.RuleResult.result.cannot.be.null");
}
if (enrolmentResultType == null) {
throw new DomainException("error.curricularRules.ruleExecutors.RuleResult.enrolmentResultType.cannot.be.null");
}
if (degreeModule == null) {
throw new DomainException("error.curricularRules.executors.RuleResult.degreeModule.cannot.be.null");
}
this.result = result;
this.enrolmentResultTypeByDegreeModule.put(degreeModule, enrolmentResultType);
}
private RuleResult(final RuleResultType result, final EnrolmentResultType enrolmentResultType,
final DegreeModule degreeModule, final Set<RuleResultMessage> messages) {
this(result, enrolmentResultType, degreeModule);
this.messages.addAll(messages);
}
public RuleResultType getResult() {
return this.result;
}
public Set<RuleResultMessage> getMessages() {
return messages;
}
public RuleResult and(final RuleResult ruleResult) {
final RuleResultType andResult = this.getResult().and(ruleResult.getResult());
final Set<RuleResultMessage> messages = new HashSet<RuleResultMessage>(getMessages());
messages.addAll(ruleResult.getMessages());
return new RuleResult(andResult, andMerge(this.enrolmentResultTypeByDegreeModule,
ruleResult.enrolmentResultTypeByDegreeModule), messages);
}
private Map<DegreeModule, EnrolmentResultType> andMerge(final Map<DegreeModule, EnrolmentResultType> left,
final Map<DegreeModule, EnrolmentResultType> right) {
for (final Entry<DegreeModule, EnrolmentResultType> each : right.entrySet()) {
if (left.containsKey(each.getKey())) {
left.put(each.getKey(), left.get(each.getKey()).and(each.getValue()));
} else {
left.put(each.getKey(), each.getValue());
}
}
return left;
}
public RuleResult or(final RuleResult ruleResult) {
final RuleResultType orResult = this.getResult().or(ruleResult.getResult());
final Set<RuleResultMessage> messages = new HashSet<RuleResultMessage>(getMessages());
messages.addAll(ruleResult.getMessages());
return new RuleResult(orResult, orMerge(this.enrolmentResultTypeByDegreeModule,
ruleResult.enrolmentResultTypeByDegreeModule), messages);
}
private Map<DegreeModule, EnrolmentResultType> orMerge(final Map<DegreeModule, EnrolmentResultType> left,
final Map<DegreeModule, EnrolmentResultType> right) {
for (final Entry<DegreeModule, EnrolmentResultType> each : right.entrySet()) {
if (left.containsKey(each.getKey())) {
left.put(each.getKey(), left.get(each.getKey()).or(each.getValue()));
} else {
left.put(each.getKey(), each.getValue());
}
}
return left;
}
public boolean isTrue() {
return getResult() == RuleResultType.TRUE;
}
public boolean isFalse() {
return getResult() == RuleResultType.FALSE;
}
public boolean isNA() {
return getResult() == RuleResultType.NA;
}
public boolean isWarning() {
return getResult() == RuleResultType.WARNING;
}
public EnrolmentResultType getEnrolmentResultTypeFor(DegreeModule degreeModule) {
return this.enrolmentResultTypeByDegreeModule.containsKey(degreeModule) ? this.enrolmentResultTypeByDegreeModule
.get(degreeModule) : EnrolmentResultType.VALIDATED;
}
public boolean isTemporaryEnrolmentResultType(final DegreeModule degreeModule) {
return getEnrolmentResultTypeFor(degreeModule) == EnrolmentResultType.TEMPORARY;
}
public boolean isImpossibleEnrolmentResultType(final DegreeModule degreeModule) {
return getEnrolmentResultTypeFor(degreeModule) == EnrolmentResultType.IMPOSSIBLE;
}
public boolean isValidated(final DegreeModule degreeModule) {
return getEnrolmentResultTypeFor(degreeModule) == EnrolmentResultType.VALIDATED;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof RuleResult) {
return this.result == ((RuleResult) obj).getResult();
}
return false;
}
public boolean hasAnyImpossibleEnrolment() {
return this.enrolmentResultTypeByDegreeModule.values().contains(EnrolmentResultType.IMPOSSIBLE);
}
@SuppressWarnings("unchecked")
static public RuleResult createInitialTrue() {
return new RuleResult(RuleResultType.TRUE, new HashMap<DegreeModule, EnrolmentResultType>(), Collections.EMPTY_SET);
}
static public RuleResult createTrue(final DegreeModule degreeModule) {
return new RuleResult(RuleResultType.TRUE, EnrolmentResultType.VALIDATED, degreeModule);
}
static public RuleResult createTrue(final EnrolmentResultType enrolmentResultType, final DegreeModule degreeModule) {
return new RuleResult(RuleResultType.TRUE, enrolmentResultType, degreeModule);
}
static public RuleResult createImpossible(final DegreeModule degreeModule, String message, String... args) {
return createTrue(EnrolmentResultType.IMPOSSIBLE, degreeModule, message, args);
}
static public RuleResult createImpossibleWithLiteralMessage(final DegreeModule degreeModule, String message) {
return new RuleResult(RuleResultType.TRUE, EnrolmentResultType.IMPOSSIBLE, degreeModule,
Collections.singleton(new RuleResultMessage(message, false)));
}
static public RuleResult createTrue(final EnrolmentResultType enrolmentResultType, final DegreeModule degreeModule,
final String message, final String... args) {
return new RuleResult(RuleResultType.TRUE, enrolmentResultType, degreeModule,
Collections.singleton(new RuleResultMessage(message, true, args)));
}
static public RuleResult createFalse(final DegreeModule degreeModuleToEvaluate) {
return createFalse(EnrolmentResultType.VALIDATED, degreeModuleToEvaluate);
}
@SuppressWarnings("unchecked")
static public RuleResult createInitialFalse() {
return new RuleResult(RuleResultType.FALSE, new HashMap<DegreeModule, EnrolmentResultType>(), Collections.EMPTY_SET);
}
static public RuleResult createFalse(final EnrolmentResultType enrolmentResultType, final DegreeModule degreeModule) {
return new RuleResult(RuleResultType.FALSE, enrolmentResultType, degreeModule);
}
static public RuleResult createFalse(final DegreeModule degreeModule, final String message, final String... args) {
return createFalse(EnrolmentResultType.VALIDATED, degreeModule, message, args);
}
static public RuleResult createFalse(final EnrolmentResultType enrolmentResultType, final DegreeModule degreeModule,
final String message, final String... args) {
return new RuleResult(RuleResultType.FALSE, enrolmentResultType, degreeModule,
Collections.singleton(new RuleResultMessage(message, args)));
}
static public RuleResult createFalseWithLiteralMessage(final DegreeModule degreeModule, final String message) {
return new RuleResult(RuleResultType.FALSE, EnrolmentResultType.VALIDATED, degreeModule,
Collections.singleton(new RuleResultMessage(message, false)));
}
static public RuleResult createNA(final DegreeModule degreeModule) {
return new RuleResult(RuleResultType.NA, EnrolmentResultType.NULL, degreeModule);
}
static public RuleResult createWarning(final DegreeModule degreeModule, final Set<RuleResultMessage> ruleResultMessages) {
return new RuleResult(RuleResultType.WARNING, EnrolmentResultType.VALIDATED, degreeModule, ruleResultMessages);
}
static public RuleResult createWarning(final DegreeModule degreeModule, final String message, final String... args) {
return createWarning(degreeModule, Collections.singleton(new RuleResultMessage(message, args)));
}
}