/*
* (c) 2008- RANDI2 Core Development Team
*
* This file is part of RANDI2.
*
* RANDI2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* RANDI2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* RANDI2. If not, see <http://www.gnu.org/licenses/>.
*/
package de.randi2.model.criteria;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import lombok.Getter;
import lombok.Setter;
import de.randi2.model.AbstractDomainObject;
import de.randi2.model.criteria.constraints.AbstractConstraint;
import de.randi2.unsorted.ConstraintViolatedException;
/**
* This class maps the needed behaviour of a Trial subject. With the Classes
* inherited from this class you can define anything you need, referring to the
* properties a trials subject should have:
* <ul>
* <li>Properties that needs to be entered</li>
* <li>Inclusion Criteria</li>
* <li>Stratification</li>
* </ul>
*
*/
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Table(name="Criterion")
public abstract class AbstractCriterion<V extends Serializable, C extends AbstractConstraint<V>> extends AbstractDomainObject {
private static final long serialVersionUID = 6845807707883121147L;
// The name of the criterion i.e. birthday
@Getter @Setter
public String name;
@Getter @Setter
public String description;
@Transient
protected List<V> configuredValues;
@Transient
public abstract List<V> getConfiguredValues();
/**
* If the object represents an inclusion criteria, this field has the
* constraints.
*/
@OneToOne(targetEntity=AbstractConstraint.class, cascade=CascadeType.ALL)
protected C inclusionConstraint;
@OneToMany(targetEntity=AbstractConstraint.class, cascade=CascadeType.ALL)
protected List<C> strata;
@Transient
public C getInclusionConstraint(){
return inclusionConstraint;
}
public abstract void setInclusionConstraint(C inclusionConstraint) throws ConstraintViolatedException;
@SuppressWarnings("unchecked")
public void setInclusionConstraintAbstract(AbstractConstraint<?> inclusionConstraint) throws ConstraintViolatedException{
setInclusionConstraint((C) inclusionConstraint);
}
@Transient
public abstract Class<C> getContstraintType();
@Transient
public List<C> getStrata(){
return strata;
}
public void setStrata(List<C> strata){
this.strata = strata;
}
public void addStrata(AbstractConstraint<?> abstractConstraint){
if(this.strata == null){
this.strata = new ArrayList<C>();
}
if(abstractConstraint != null){
this.strata.add((C) abstractConstraint);
}
}
public C stratify(V value) throws ConstraintViolatedException{
this.isValueCorrect(value);
if(strata==null || strata.isEmpty())
return null;
for(C stratum : strata){
if(stratum.checkValue(value))
return stratum;
}
throw new ConstraintViolatedException();
// throw new Randi2Error("Valid value could not be assigned to any stratum.");
}
@Transient
public boolean isInclusionCriterion(){
return inclusionConstraint!=null;
}
public abstract void isValueCorrect(V value) throws ConstraintViolatedException;
public boolean checkValue(V value){
try{
isValueCorrect(value);
return true;
}
catch(ConstraintViolatedException e){
return false;
}
}
}