Commit 74ebb4b8 authored by Clement Frainay's avatar Clement Frainay
Browse files

Merge branch 'EntityEqualityAndProtectedParticipants' into 'develop'

Remove equals overriding of BioEntity and protects creation of BioParticipant

See merge request !6
parents 87cb40ea b5c76024
Pipeline #48677 passed with stages
in 3 minutes and 13 seconds
......@@ -15,12 +15,10 @@ public class FormulaParser {
String formula;
Pattern inorgaRegex;
Pattern groupMatch;
Pattern genericFormula = Pattern.compile("^([\\*\\(\\)A-Z][a-z]*\\d*)+$");;
List<String> atoms = Arrays.asList("H","B","C","N","O","F","Na","Mg","Al","Si","P","S","Cl","K","Ca","Cr","Mn","Fe","Co","Cu","Zn","Se","Mo","Cd","Sn","I");
public FormulaParser(String formula){
if(StringUtils.isVoid(formula) || !genericFormula.matcher(formula).find()) throw new IllegalArgumentException("Unable to parse formula");
if(StringUtils.isVoid(formula) || ! StringUtils.checkMetaboliteFormula(formula)) throw new IllegalArgumentException("Unable to parse formula");
this.formula=formula;
}
......
......@@ -47,7 +47,7 @@ import fr.inrae.toulouse.metexplore.met4j_core.utils.StringUtils;
*/
public abstract class BioEntity {
private final String id;
final String id;
private String name;
private ArrayList<String> synonyms = new ArrayList<>();
private String comment;
......@@ -103,26 +103,6 @@ public abstract class BioEntity {
this.setAttributes(new HashMap<>(e.getAttributes()));
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BioEntity bioEntity = (BioEntity) o;
return id.equals(bioEntity.id);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(id);
}
/**
* Set the name of the entity
*
......
......@@ -54,8 +54,8 @@ public class BioEnzymeParticipant extends BioParticipant {
* @param physicalEntity the physical entity that is contained in the enzyme
* @param stoichiometry the number of unities of the physical entity
*/
public BioEnzymeParticipant(BioPhysicalEntity physicalEntity, Double stoichiometry) {
super(physicalEntity, stoichiometry);
protected BioEnzymeParticipant(BioPhysicalEntity physicalEntity, Double stoichiometry) {
super(physicalEntity.getId() + "__" + stoichiometry, physicalEntity, stoichiometry);
}
/**
......@@ -65,7 +65,7 @@ public class BioEnzymeParticipant extends BioParticipant {
* The stoichiometry is put to 1.
*/
public BioEnzymeParticipant(BioPhysicalEntity physicalEntity) {
super(physicalEntity, 1.0);
this(physicalEntity, 1.0);
}
/**
......@@ -92,7 +92,7 @@ public class BioEnzymeParticipant extends BioParticipant {
}
String buffer = quantityStr + " " + this.getId();
String buffer = quantityStr + " " + this.getPhysicalEntity().getId();
return buffer;
......
......@@ -41,10 +41,7 @@ package fr.inrae.toulouse.metexplore.met4j_core.biodata;
import fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
/**
......@@ -72,6 +69,10 @@ public class BioNetwork extends BioEntity {
private final BioCollection<BioEnzyme> enzymes = new BioCollection<>();
private final BioCollection<BioReactant> reactants = new BioCollection<>();
private final BioCollection<BioEnzymeParticipant> enzymeParticipants = new BioCollection<>();
/**
* <p>Constructor for BioNetwork.</p>
*
......@@ -533,7 +534,7 @@ public class BioNetwork extends BioEntity {
* @param reaction a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReaction}
* @param reactants a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection} {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReactant}
*/
public void affectLeft(BioReaction reaction, BioCollection<BioReactant> reactants) {
protected void affectLeft(BioReaction reaction, BioCollection<BioReactant> reactants) {
this.affectLeft(reaction, reactants.toArray(new BioReactant[0]));
}
......@@ -613,7 +614,7 @@ public class BioNetwork extends BioEntity {
* @param reaction a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReaction}
* @param reactants a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection} {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReactant} of {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReactant}
*/
public void affectRight(BioReaction reaction, BioCollection<BioReactant> reactants) {
protected void affectRight(BioReaction reaction, BioCollection<BioReactant> reactants) {
this.affectRight(reaction, reactants.toArray(new BioReactant[0]));
}
......@@ -629,8 +630,27 @@ public class BioNetwork extends BioEntity {
removeSideReaction(e, localisation, reaction, BioReaction.Side.RIGHT);
}
/**
* get a reactant with the same metabolite, stoichiometry and compartment
*
* @param metabolite
* @param stoichiometry
* @param compartment
* @return
*/
protected BioReactant getReactant(BioMetabolite metabolite, Double stoichiometry, BioCompartment compartment) {
Optional<BioReactant> any = this.reactants.stream()
.filter(r -> r.getMetabolite().equals(metabolite) &&
r.getQuantity().equals(stoichiometry)
&& r.getLocation().equals(compartment)).findAny();
if (any.isPresent()) {
return any.get();
}
return null;
}
private void affectSideReaction(BioReaction reaction, Double stoichiometry, BioCompartment localisation, BioReaction.Side side, BioMetabolite e) {
BioReactant reactant = new BioReactant(e, stoichiometry, localisation);
// The network must contain the compartment
if (!this.compartments.contains(localisation)) {
......@@ -651,6 +671,13 @@ public class BioNetwork extends BioEntity {
throw new IllegalArgumentException("Reaction " + reaction.getId() + " not in the network");
}
BioReactant reactant = this.getReactant(e, stoichiometry, localisation);
if (reactant == null) {
reactant = new BioReactant(e, stoichiometry, localisation);
this.reactants.add(reactant);
}
if (side.equals(BioReaction.Side.LEFT)) {
reaction.getLeftReactants().add(reactant);
} else {
......@@ -658,11 +685,29 @@ public class BioNetwork extends BioEntity {
}
}
private void addReactant(BioReactant reactant) {
this.reactants.add(reactant);
}
/**
* Add reactants in the list of reactants
* @param reactants
*/
protected void addReactants(BioReactant ...reactants) {
for(BioReactant r : reactants) {
this.addReactant(r);
}
}
private void affectSideReaction(BioReactant reactant, BioReaction reaction, BioReaction.Side side) {
BioCompartment localisation = reactant.getLocation();
if (! this.reactants.contains(reactant)) {
throw new IllegalArgumentException("Reactant " + reactant.getId() + " not in the network");
}
// The network must contain the compartment
if (!this.compartments.contains(localisation)) {
throw new IllegalArgumentException("Compartment " + localisation.getId() + " not in the network");
......@@ -685,9 +730,13 @@ public class BioNetwork extends BioEntity {
}
if (side.equals(BioReaction.Side.LEFT)) {
reaction.getLeftReactants().add(reactant);
if (!reaction.getLeftReactants().containsId(reactant.getId())) {
reaction.getLeftReactants().add(reactant);
}
} else {
reaction.getRightReactants().add(reactant);
if (!reaction.getRightReactants().containsId(reactant.getId())) {
reaction.getRightReactants().add(reactant);
}
}
}
......@@ -786,6 +835,23 @@ public class BioNetwork extends BioEntity {
}
/**
* Get enzyme participant with the same quantity and the same entity
*
* @param quantity
* @param unit
* @return
*/
protected BioEnzymeParticipant getEnzymeParticipant(BioPhysicalEntity unit, Double quantity) {
Optional<BioEnzymeParticipant> any = this.enzymeParticipants.stream()
.filter(e -> e.getPhysicalEntity().equals(unit) && e.getQuantity().equals(quantity))
.findAny();
if (any.isPresent()) {
return any.get();
} else return null;
}
/**
* Add a subunit to an enzymes
*
......@@ -796,8 +862,6 @@ public class BioNetwork extends BioEntity {
*/
private void affectSubUnit(BioEnzyme enzyme, Double quantity, BioPhysicalEntity unit) {
BioEnzymeParticipant p = new BioEnzymeParticipant(unit, quantity);
if (!this.contains(enzyme)) {
throw new IllegalArgumentException("Enzyme " + enzyme.getId() + " not present in the network");
}
......@@ -806,6 +870,12 @@ public class BioNetwork extends BioEntity {
throw new IllegalArgumentException("Physical entity " + unit.getId() + " not present in the network");
}
BioEnzymeParticipant p = this.getEnzymeParticipant(unit, quantity);
if (p == null) {
p = new BioEnzymeParticipant(unit, quantity);
this.enzymeParticipants.add(p);
}
enzyme.addParticipant(p);
}
......@@ -819,6 +889,9 @@ public class BioNetwork extends BioEntity {
*/
private void affectSubUnit(BioEnzyme enzyme, BioEnzymeParticipant unit) {
if(! this.enzymeParticipants.contains(unit)) {
throw new IllegalArgumentException("Enzyme participant " + unit.getId() + " not present in the network");
}
if (!this.contains(enzyme)) {
throw new IllegalArgumentException("Enzyme " + enzyme.getId() + " not present in the network");
......@@ -828,7 +901,9 @@ public class BioNetwork extends BioEntity {
throw new IllegalArgumentException("Physical entity " + unit.getPhysicalEntity().getId() + " not present in the network");
}
enzyme.addParticipant(unit);
if(! enzyme.getParticipants().containsId(unit.getId())) {
enzyme.addParticipant(unit);
}
}
......@@ -882,7 +957,7 @@ public class BioNetwork extends BioEntity {
* @param enzyme a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioEnzyme}
* @param units a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection} of {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioEnzymeParticipant}
*/
public void affectSubUnit(BioEnzyme enzyme, BioCollection<BioEnzymeParticipant> units) {
protected void affectSubUnit(BioEnzyme enzyme, BioCollection<BioEnzymeParticipant> units) {
for (BioEnzymeParticipant unit : units) {
affectSubUnit(enzyme, unit);
......@@ -1178,7 +1253,7 @@ public class BioNetwork extends BioEntity {
}
/**
* @param m a {@link BioMetabolite}
* @param m a {@link BioMetabolite}
* @param isSubstrate a {@link Boolean} indicating if the metabolite is a substrate or a product
* @return a {@link BioCollection} of {@link BioReaction}
*/
......@@ -1776,4 +1851,56 @@ public class BioNetwork extends BioEntity {
public int hashCode() {
return Objects.hash(super.hashCode(), pathways, metabolites, proteins, genes, reactions, compartments, enzymes);
}
/**
* @param e
* @return
*/
public Boolean containsEntityWithSameId(BioEntity e) {
if (e == null) {
throw new NullPointerException();
}
String id = e.getId();
Boolean flag;
if (e instanceof BioPathway) {
flag = this.pathways.containsId(id);
} else if (e instanceof BioMetabolite) {
flag = this.metabolites.containsId(id);
} else if (e instanceof BioProtein) {
flag = this.proteins.containsId(id);
} else if (e instanceof BioGene) {
flag = this.genes.containsId(id);
} else if (e instanceof BioReaction) {
flag = this.reactions.containsId(id);
} else if (e instanceof BioCompartment) {
flag = this.compartments.containsId(id);
} else if (e instanceof BioEnzyme) {
flag = this.enzymes.containsId(id);
} else {
throw new IllegalArgumentException(
"BioEntity \"" + e.getClass().getSimpleName() + "\" not supported by BioNetwork");
}
return flag;
}
/**
* Adds enzymes participants in the network
* @param enzymeParticipants
*/
protected void addEnzymeParticipants(BioEnzymeParticipant ...enzymeParticipants) {
for(BioEnzymeParticipant ep : enzymeParticipants) {
this.addEnzymeParticipant(ep);
}
}
private void addEnzymeParticipant(BioEnzymeParticipant ep) {
this.enzymeParticipants.add(ep);
}
}
......@@ -38,6 +38,7 @@ package fr.inrae.toulouse.metexplore.met4j_core.biodata;
import fr.inrae.toulouse.metexplore.met4j_core.utils.ErrorUtils;
import javax.annotation.Nonnull;
import java.util.Objects;
/**
......@@ -48,9 +49,9 @@ import java.util.Objects;
*/
public abstract class BioParticipant extends BioEntity {
private BioPhysicalEntity physicalEntity;
private final BioPhysicalEntity physicalEntity;
private Double quantity;
private final Double quantity;
/**
* Constructor
......@@ -58,13 +59,20 @@ public abstract class BioParticipant extends BioEntity {
* @param physicalEntity a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioPhysicalEntity}
* @param quantity number of units of physicalEntity
*/
public BioParticipant(BioPhysicalEntity physicalEntity, Double quantity) {
super(physicalEntity.getId());
public BioParticipant(String id, @Nonnull BioPhysicalEntity physicalEntity, Double quantity) {
super(id);
this.physicalEntity=physicalEntity;
this.setQuantity(quantity);
if(Double.isNaN(quantity) || Double.isInfinite(quantity) || quantity <= 0)
{
ErrorUtils.error("Illegal argument for "+quantity+" "+this.getPhysicalEntity().getId()+": the quantity must be finite and positive");
throw new IllegalArgumentException();
}
this.quantity = quantity;
}
/**
* <p>Getter for the field <code>physicalEntity</code>.</p>
*
......@@ -75,18 +83,6 @@ public abstract class BioParticipant extends BioEntity {
}
/**
* <p>Setter for the field <code>physicalEntity</code>.</p>
*
* @param physicalEntity the physicalEntity to set
*/
public void setPhysicalEntity(BioPhysicalEntity physicalEntity) {
this.physicalEntity = physicalEntity;
}
/**
* <p>Getter for the field <code>quantity</code>.</p>
*
......@@ -97,28 +93,11 @@ public abstract class BioParticipant extends BioEntity {
}
/**
* <p>Setter for the field <code>quantity</code>.</p>
*
* @param quantity the quantity to set
*/
public void setQuantity(Double quantity) {
if(Double.isNaN(quantity) || Double.isInfinite(quantity) || quantity <= 0)
{
ErrorUtils.error("Illegal argument for "+quantity+" "+this.getPhysicalEntity().getId()+": the quantity must be finite and positive");
throw new IllegalArgumentException();
}
this.quantity = quantity;
}
/** {@inheritDoc} */
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
BioParticipant that = (BioParticipant) o;
return Objects.equals(physicalEntity, that.physicalEntity) &&
Objects.equals(quantity, that.quantity);
......
......@@ -35,6 +35,7 @@
*/
package fr.inrae.toulouse.metexplore.met4j_core.biodata;
import javax.annotation.Nonnull;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
......@@ -49,7 +50,7 @@ import java.util.Objects;
*/
public class BioReactant extends BioParticipant {
private BioCompartment location = null;
private final BioCompartment location;
/**
* Constructor
......@@ -58,9 +59,9 @@ public class BioReactant extends BioParticipant {
* @param stoichiometry stoichiometric coefficient
* @param location a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioCompartment}
*/
public BioReactant(BioMetabolite metabolite, Double stoichiometry, BioCompartment location) {
super(metabolite, stoichiometry);
this.setLocation(location);
protected BioReactant(@Nonnull BioMetabolite metabolite, Double stoichiometry, @Nonnull BioCompartment location) {
super(metabolite.getId()+"__"+stoichiometry+"__"+location.getId(), metabolite, stoichiometry);
this.location = location;
}
/**
......@@ -72,15 +73,6 @@ public class BioReactant extends BioParticipant {
return location;
}
/**
* Set location
*
* @param location a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioCompartment}
*/
protected void setLocation(BioCompartment location) {
this.location = location;
}
/**
* Get the associated metabolite
*
......@@ -114,7 +106,7 @@ public class BioReactant extends BioParticipant {
StringBuilder buffer = new StringBuilder(quantityStr);
buffer.append(" ");
buffer.append(this.getId());
buffer.append(this.getPhysicalEntity().getId());
if (this.getLocation() != null) {
buffer.append("[");
buffer.append(this.getLocation().getId());
......
......@@ -198,7 +198,15 @@ public class BioCollection<E extends BioEntity> implements Collection<E> {
/** {@inheritDoc} */
@Override
public boolean add(E e) {
entities.put(e.getId(), e);
if(entities.containsValue(e)) {
return false;
}
else {
if (entities.keySet().contains(e.getId())) {
throw new IllegalArgumentException("An entity with the same id (" + e.getId() + ") is already present in the BioCollection");
}
entities.put(e.getId(), e);
}
return true;
}
......
......@@ -136,12 +136,14 @@ public class BioNetworkUtils {
}
for (BioMetabolite metabolite : metabolitesToCopy) {
BioMetabolite newMetabolite = new BioMetabolite(metabolite);
networkOut.add(newMetabolite);
BioMetabolite newMetabolite;
if (!networkOut.containsEntityWithSameId(metabolite)) {
newMetabolite = new BioMetabolite(metabolite);
networkOut.add(newMetabolite);
}
}
// Copy compartments (empty for the moment)
// Copy metabolites
// Copy compartments
BioCollection<BioCompartment> compartmentsToCopy = networkIn.getCompartmentsView();
if (keepPrevious) {
compartmentsToCopy.removeAll(networkOut.getCompartmentsView());
......@@ -151,7 +153,7 @@ public class BioNetworkUtils {
BioCompartment newCpt;
if (compartmentsToCopy.contains(cpt)) {
if (compartmentsToCopy.contains(cpt) && (!networkOut.containsEntityWithSameId(cpt))) {
newCpt = new BioCompartment(cpt);
networkOut.add(newCpt);
} else {
......@@ -176,8 +178,10 @@ public class BioNetworkUtils {
}
for (BioGene gene : genesToCopy) {
BioGene newGene = new BioGene(gene);
networkOut.add(newGene);
if (!networkOut.containsEntityWithSameId(gene)) {
BioGene newGene = new BioGene(gene);
networkOut.add(newGene);
}
}
}
......@@ -191,7 +195,7 @@ public class BioNetworkUtils {
BioProtein newProtein;
if (proteinsToCopy.contains(protein)) {
if (proteinsToCopy.contains(protein) && (!networkOut.containsEntityWithSameId(protein))) {
newProtein = new BioProtein(protein);
networkOut.add(newProtein);
} else {
......@@ -218,7 +222,7 @@ public class BioNetworkUtils {
BioEnzyme newEnzyme;
if (enzymesToCopy.contains(enzyme)) {
if (enzymesToCopy.contains(enzyme) && !networkOut.containsEntityWithSameId(enzyme)) {
newEnzyme = new BioEnzyme(enzyme);