From 42d357fb260bb063b897eaf2c848348d1e3735db Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 5 Apr 2018 17:55:22 +0200
Subject: [PATCH] update on recon annotator after changes in API

---
 .../services/annotators/ElementAnnotator.java | 1231 +++++++++--------
 .../services/annotators/ReconAnnotator.java   |  507 ++++---
 .../annotators/ReconAnnotatorTest.java        |  631 ++++-----
 .../lcsb/mapviewer/model/map/MiriamType.java  |    2 +-
 4 files changed, 1238 insertions(+), 1133 deletions(-)

diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java
index 7be1c6bde1..520c32d4f3 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java
@@ -30,598 +30,641 @@ import lcsb.mapviewer.model.user.UserAnnotatorsParam;
  */
 public abstract class ElementAnnotator extends CachableInterface {
 
-	/**
-	 * Default class logger.
-	 */
-	private final Logger													 logger				= Logger.getLogger(ElementAnnotator.class);
-
-	/**
-	 * List of classes that can be annotated by this {@link IElementAnnotator
-	 * annotator}.
-	 */
-	private final List<Class<? extends BioEntity>> validClasses	= new ArrayList<>();
-
-	/**
-	 * Should be this annotator used as a default annotator.
-	 */
-	private boolean																 isDefault		= false;
-	
-	/**
-	 * Parameters which this annotator can be provided. Should be set in constructor.
-	 */
-	protected List<AnnotatorParamDefinition> 											paramsDefs		= new ArrayList<>();
-
-	/**
-	 * Default constructor.
-	 * 
-	 * @param validClasses
-	 *          list of classes for which this annotator is valid
-	 * @param isDefault
-	 *          {@link #isDefault}
-	 * @param clazz
-	 *          type that defines this interface
-	 */
-	@SuppressWarnings("unchecked")
-	public ElementAnnotator(Class<? extends CachableInterface> clazz, Class<?>[] validClasses, boolean isDefault) {
-		super(clazz);
-		for (Class<?> validClass : validClasses) {
-			if (BioEntity.class.isAssignableFrom(validClass)) {
-				addValidClass((Class<? extends BioEntity>) validClass);
-			} else {
-				throw new InvalidArgumentException("Cannot pass class of type: " + validClass + ". Only classes extending " + BioEntity.class + " are accepted.");
-			}
-		}
-		this.isDefault = isDefault;
-	}
-
-	/**
-	 * Annotate element.
-	 * 
-	 * @param element
-	 *          object to be annotated
-	 * @throws AnnotatorException
-	 *           thrown when there is a problem with annotating not related to
-	 *           data
-	 */
-	public abstract void annotateElement(BioEntity element) throws AnnotatorException;
-	
-	/**
-	 * Annotate element using parameters.
-	 * 
-	 * @param element
-	 *          object to be annotated
-	 * @param parameters
-	 * 			list of parameters passed to the annotator which is expected to
-	 * 			be in the same order as its {@link this#parameterDefs}
-	 * @throws AnnotatorException
-	 *           thrown when there is a problem with annotating not related to
-	 *           data
-	 */
-	public void annotateElement(BioEntity element, List<UserAnnotatorsParam> parameters) throws AnnotatorException {
-		annotateElement(element);
-	}
-
-	/**
-	 * Returns a list of all classes that can be annotated using this annotator.
-	 * 
-	 * @return a list of all classes that can be annotated using this annotator
-	 */
-	public List<Class<? extends BioEntity>> getValidClasses() {
-		return validClasses;
-	}
-
-	/**
-	 * Returns <code>true</code> if this annotator can annotate the object given
-	 * in the parameter.
-	 * 
-	 * @param object
-	 *          object to be tested if can be annotated
-	 * @return <code>true</code> if object can be annotated by this annotator,
-	 *         <code>false</code> otherwise
-	 */
-	public boolean isAnnotatable(BioEntity object) {
-		Class<?> clazz = object.getClass();
-		for (Class<?> validClazz : getValidClasses()) {
-			if (validClazz.isAssignableFrom(clazz)) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Adds a class to list of classes that can be annotated by the annotator.
-	 * 
-	 * @param clazz
-	 *          class to add
-	 */
-	private void addValidClass(Class<? extends BioEntity> clazz) {
-		validClasses.add(clazz);
-	}
-
-	/**
-	 * Returns the common name that should be presented to user.
-	 * 
-	 * @return the common name
-	 */
-	public abstract String getCommonName();
-
-	/**
-	 * Returns url to the external resource used for annotation.
-	 * 
-	 * @return url
-	 */
-	public abstract String getUrl();
-	
-	/**
-	 * Provides description of the extraction process 
-	 * for {@link ElementAnnotator} to be used in the front end.
-	 * @return 
-	 * 		the description
-	 */
-	public String getDescription(){
-		return "";		
-	}
-		
-	/**
-	 * Provides description for {@link ElementAnnotator} and {@link MiriamType} pair
-	 * to be used in the frontend.
-	 * @param mt 
-	 * 		{@link MiriamType} annotated by this annotator.
-	 * @return 
-	 * 		the description
-	 */	
-	public String getDescription(MiriamType mt){
-		return "";		
-	}
-
-	/**
-	 * Provides description for {@link ElementAnnotator}, {@link MiriamType} and
-	 * {@link MiriamRelationType} triplet to be used in the frontend.
-	 * @param mt 
-	 * 		{@link MiriamType} annotated by this annotator
-	 * @param relationType
-	 * 		{@link MiriamRelationType} annotated by this annotator.
-	 * @return
-	 * 		the description
-	 */
-	public String getDescription(MiriamType mt, MiriamRelationType relationType){
-		return "";		
-	}
-	
-	/**
-	 * Returns list with definitions of the parameters available for this annotator.
-	 * @return the parameters {@link AnnotatorParamDefinition} list
-	 */	
-	public Collection<AnnotatorParamDefinition> getParametersDefinitions(){
-		return paramsDefs;
-	}
-
-	/**
-	 * Returns <code>true</code> if this annotator can annotate the object of
-	 * given class type.
-	 * 
-	 * @param clazz
-	 *          class to be tested if can be annotated
-	 * @return <code>true</code> if class can be annotated by this annotator,
-	 *         <code>false</code> otherwise
-	 */
-	public boolean isAnnotatable(Class<?> clazz) {
-		for (Class<?> clazz2 : validClasses) {
-			if (clazz2.isAssignableFrom(clazz)) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * 
-	 * @return {@link #isDefault}
-	 */
-	public boolean isDefault() {
-		return isDefault;
-	}
-
-	/**
-	 * Sets symbol value to the element.
-	 * 
-	 * @param element
-	 *          element where we change data
-	 * @param symbol
-	 *          new symbol
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setSymbol(BioEntity element, String symbol, String prefix) {
-		if (element.getSymbol() == null || element.getSymbol().equals("") || element.getSymbol().equals(symbol)) {
-			element.setSymbol(symbol);
-		} else {
-			logger.warn(prefix + "Symbols doesn't match: \"" + symbol + "\", \"" + element.getSymbol() + "\"");
-		}
-		if (element.getName() == null || element.getName().equals("")) {
-			element.setName(symbol);
-		}
-	}
-
-	/**
-	 * Sets synonyms to the element.
-	 * 
-	 * @param element
-	 *          element where we change data
-	 * @param synonyms
-	 *          new synonyms list
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setSynonyms(BioEntity element, Collection<String> synonyms, String prefix) {
-		if (element.getSynonyms() == null || element.getSynonyms().size() == 0) {
-			List<String> sortedSynonyms = new ArrayList<>();
-			sortedSynonyms.addAll(synonyms);
-			Collections.sort(sortedSynonyms);
-
-			element.setSynonyms(sortedSynonyms);
-		} else {
-			logger.warn(prefix + "Synonyms don't match: \"" + synonyms + "\", \"" + element.getSynonyms() + "\"");
-		}
-	}
-
-	/**
-	 * Sets name to the element.
-	 * 
-	 * @param element
-	 *          element where we change data
-	 * @param name
-	 *          new name
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setFullName(Element element, String name, String prefix) {
-		if (element.getFullName() == null || element.getFullName().equals("") || element.getFullName().equals(name)) {
-			element.setFullName(name);
-		} else {
-			logger.warn(prefix + "Names doesn't match (" + getCommonName() + " annotator and current data): \"" + name + "\", \"" + element.getFullName() + "\"");
-		}
-	}
-
-	/**
-	 * Adds description to {@link BioEntity#getNotes()}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param description
-	 *          value to set
-	 */
-	protected void setDescription(BioEntity element, String description) {
-		if (description != null) {
-			if (element.getNotes() == null || element.getNotes().equals("") || element.getNotes().equals(description)) {
-				element.setNotes(description);
-			} else if (!element.getNotes().toLowerCase().contains(description.toLowerCase())) {
-				element.setNotes(element.getNotes() + "\n" + description);
-			}
-		}
-	}
-
-	/**
-	 * Adds {@link MiriamType#HMDB} annotation to element.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          annotation identifier
-	 */
-	protected void addHmdbMiriam(BioEntity element, String value) {
-		element.addMiriamData(createMiriamData(MiriamType.HMDB, value));
-	}
-
-	/**
-	 * Sets {@link CellDesignerChemical#inChI}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param prefix
-	 *          prefix used in warnings
-	 * @param value
-	 *          value to set
-	 */
-	protected void setInchi(Chemical element, String value, String prefix) {
-		if (element.getInChI() == null || element.getInChI().isEmpty() || element.getInChI().equals(value)) {
-			element.setInChI(value);
-		} else {
-			logger.warn(prefix + "InChI in db different: \"" + element.getInChI() + "\", " + value);
-		}
-
-	}
-
-	/**
-	 * Sets {@link CellDesignerChemical#inChIKey}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param prefix
-	 *          prefix used in warnings
-	 * @param value
-	 *          value to set
-	 */
-	protected void setInchiKey(Chemical element, String value, String prefix) {
-		if (element.getInChIKey() == null || element.getInChIKey().equals("")) {
-			element.setInChIKey(value);
-		} else if (!element.getInChIKey().equalsIgnoreCase(value)) {
-			logger.warn(prefix + "Different inchikey for chemical: " + element.getInChIKey() + ", " + value);
-		}
-
-	}
-
-	/**
-	 * Sets {@link CellDesignerChemical#smiles}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param prefix
-	 *          prefix used in warnings
-	 * @param value
-	 *          value to set
-	 */
-	protected void setSmile(Chemical element, String value, String prefix) {
-		if (element.getSmiles() == null || element.getSmiles().isEmpty() || element.getSmiles().equals(value)) {
-			element.setSmiles(value);
-		} else {
-			logger.warn(prefix + "InChI in db different: \"" + element.getSmiles() + "\", " + value);
-		}
-
-	}
-
-	/**
-	 * Adds {@link MiriamType#CHEBI} annotation to element.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          annotation identifier
-	 */
-	protected void addChebiMiriam(BioEntity element, String value) {
-		if (!value.startsWith("CHEBI:")) {
-			value = "CHEBI:" + value;
-		}
-		element.addMiriamData(createMiriamData(MiriamType.CHEBI, value));
-	}
-
-	/**
-	 * Sets {@link Species#charge}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          value to set
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setCharge(Species element, String value, String prefix) {
-		Integer charge = Integer.parseInt(value);
-		if (element.getCharge() == null || element.getCharge() == 0 || element.getCharge().equals(charge)) {
-			element.setCharge(Integer.valueOf(charge));
-		} else {
-			logger.warn(prefix + "Charge in db different: \"" + element.getCharge() + "\", " + charge);
-		}
-
-	}
-
-	/**
-	 * Adds {@link MiriamType#PUBCHEM} annotation to element.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          annotation identifier
-	 */
-	protected void addPubchemMiriam(BioEntity element, String value) {
-		element.addMiriamData(createMiriamData(MiriamType.PUBCHEM, value));
-	}
-
-	/**
-	 * Adds {@link MiriamType#COG} annotation to element.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          annotation identifier
-	 */
-	protected void addCogMiriam(BioEntity element, String value) {
-		element.addMiriamData(createMiriamData(MiriamType.COG, value));
-	}
-
-	/**
-	 * Sets {@link Reaction#subsystem}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          value to set
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setSubsystem(Reaction element, String value, String prefix) {
-		if (element.getSubsystem() == null || element.getSubsystem().isEmpty() || element.getSubsystem().equals(value)) {
-			element.setSubsystem(value);
-		} else {
-			logger.warn(prefix + "Subsystem in db different: \"" + element.getSubsystem() + "\", " + value);
-		}
-	}
-
-	/**
-	 * Adds {@link MiriamType#EC} annotation to element.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          annotation identifier
-	 */
-	protected void addEcMiriam(BioEntity element, String value) {
-		element.addMiriamData(createMiriamData(MiriamType.EC, value));
-	}
-
-	/**
-	 * Adds {@link MiriamType#KEGG_COMPOUND} or {@link MiriamType#KEGG_REACTION}
-	 * annotation to element.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          annotation identifier
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void addKeggMiriam(BioEntity element, String value, String prefix) {
-		if (value.startsWith("C")) {
-			MiriamData md = createMiriamData(MiriamType.KEGG_COMPOUND, value);
-			element.addMiriamData(md);
-		} else if (value.startsWith("R")) {
-			MiriamData md = createMiriamData(MiriamType.KEGG_REACTION, value);
-			element.addMiriamData(md);
-		} else if (value.startsWith("K")) {
-			MiriamData md = createMiriamData(MiriamType.KEGG_ORTHOLOGY, value);
-			element.addMiriamData(md);
-		} else {
-			logger.warn(prefix + "Unknown Kegg identifier type (only Kegg compounds and reactions are supported): \"" + value + "\"");
-		}
-	}
-
-	/**
-	 * Sets {@link BioEntity#getFormula()}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          value to set
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setFormula(BioEntity element, String value, String prefix) {
-		if (element.getFormula() == null || element.getFormula().isEmpty() || element.getFormula().equals(value)) {
-			element.setFormula(value);
-		} else {
-			logger.warn(prefix + "Formula in db different: \"" + element.getFormula() + "\", \"" + value + "\"");
-		}
-	}
-
-	/**
-	 * Sets {@link BioEntity#getAbbreviation()}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          value to set
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setAbbreviation(BioEntity element, String value, String prefix) {
-		if (element.getAbbreviation() == null || element.getAbbreviation().isEmpty() || element.getAbbreviation().equals(value)) {
-			element.setAbbreviation(value);
-		} else if (!element.getAbbreviation().contains(value)) {
-			logger.warn(prefix + "Abbreviation in db different: \"" + element.getAbbreviation() + "\", " + value);
-		}
-	}
-
-	/**
-	 * Sets {@link Reaction#getMechanicalConfidenceScore()}.
-	 * 
-	 * @param element
-	 *          element where annotation should be added
-	 * @param value
-	 *          value to set
-	 * @param prefix
-	 *          prefix used in warnings
-	 */
-	protected void setMcs(Reaction element, String value, String prefix) {
-		if (element.getMechanicalConfidenceScore() == null || element.getMechanicalConfidenceScore() == 0
-				|| element.getMechanicalConfidenceScore().toString().equals(value)) {
-			element.setMechanicalConfidenceScore(Integer.valueOf(value));
-		} else {
-			logger.warn(prefix + "MCS in db different: \"" + element.getMechanicalConfidenceScore() + "\", \"" + value + "\"");
-		}
-	}
-	
-	/**
-	 * Sets definitions of parameters for given annotator.
-	 * @param paramDefs
-	 * 		definitions to be set
-	 */	
-	public void setParametersDefinitions(List<AnnotatorParamDefinition> paramDefs){
-		this.paramsDefs = paramDefs;
-	}
-	
-	/**
-	 * Adds parameter definition to the definitions of parameters for given annotator 
-	 * @param paramDef
-	 * 		parameter definition to be added 
-	 */
-	public void addParameterDefinition(AnnotatorParamDefinition paramDef){
-		this.paramsDefs.add(paramDef);
-	}
-	
-	/**
-	 * Sets MiriamData.annotator to this annotator
-	 * 
-	 * @param md
-	 *		data for which the annotator is to be set
-	 */
-	private void setAnnotator(MiriamData md){
-		md.setAnnotator(this.getClass());		
-	}
-	
-	/**
-	 * Creates {@link MiriamData} and sets its annotator to this annotator
-	 * @return
-	 * 		created {@link MiriamData}
-	 */
-	protected MiriamData createMiriamData(){
-		MiriamData md = new MiriamData();
-		setAnnotator(md);
-		return md;		
-	}
-	
-	/**
-	 * Creates {@link MiriamData} and sets its annotator to this annotator
-	 * @param _md
-	 * 		{@link MiriamData} based on which the new {@link MiriamData} should be created
-	 * @return
-	 * 		created {@link MiriamData}
-	 */
-	protected MiriamData createMiriamData(MiriamData _md){
-		MiriamData md = new MiriamData(_md);
-		setAnnotator(md);
-		return md;		
-	}
-	
-	/**
-	 * Creates {@link MiriamData} and sets its annotator to this annotator
-	 * @param mt
-	 * 		{@link MiriamType} to be set
-	 * @param resource
-	 * 		resource to be set
-	 * @return
-	 * 		created {@link MiriamData}
-	 */
-	protected MiriamData createMiriamData(MiriamType mt, String resource){
-		MiriamData md = new MiriamData(mt, resource);
-		setAnnotator(md);
-		return md;		
-	}
-	
-	/**
-	 * Creates {@link MiriamData} and sets its annotator to this annotator
-	 * @param relationType
-	 * 		{@link MiriamRelationType} to be set
-	 * @param mt
-	 * 		{@link MiriamType} to be set
-	 * @param resource
-	 * 		resource to be set
-	 * @return
-	 * 		created {@link MiriamData}
-	 */
-	protected MiriamData createMiriamData(MiriamRelationType relationType, MiriamType mt, String resource){
-		MiriamData md = new MiriamData(relationType, mt, resource);
-		setAnnotator(md);
-		return md;		
-	}	
+  /**
+   * Default class logger.
+   */
+  private final Logger logger = Logger.getLogger(ElementAnnotator.class);
+
+  /**
+   * List of classes that can be annotated by this {@link IElementAnnotator
+   * annotator}.
+   */
+  private final List<Class<? extends BioEntity>> validClasses = new ArrayList<>();
+
+  /**
+   * Should be this annotator used as a default annotator.
+   */
+  private boolean isDefault = false;
+
+  /**
+   * Parameters which this annotator can be provided. Should be set in
+   * constructor.
+   */
+  protected List<AnnotatorParamDefinition> paramsDefs = new ArrayList<>();
+
+  /**
+   * Default constructor.
+   * 
+   * @param validClasses
+   *          list of classes for which this annotator is valid
+   * @param isDefault
+   *          {@link #isDefault}
+   * @param clazz
+   *          type that defines this interface
+   */
+  @SuppressWarnings("unchecked")
+  public ElementAnnotator(Class<? extends CachableInterface> clazz, Class<?>[] validClasses, boolean isDefault) {
+    super(clazz);
+    for (Class<?> validClass : validClasses) {
+      if (BioEntity.class.isAssignableFrom(validClass)) {
+        addValidClass((Class<? extends BioEntity>) validClass);
+      } else {
+        throw new InvalidArgumentException("Cannot pass class of type: " + validClass + ". Only classes extending "
+            + BioEntity.class + " are accepted.");
+      }
+    }
+    this.isDefault = isDefault;
+  }
+
+  /**
+   * Annotate element.
+   * 
+   * @param element
+   *          object to be annotated
+   * @throws AnnotatorException
+   *           thrown when there is a problem with annotating not related to data
+   */
+  public abstract void annotateElement(BioEntity element) throws AnnotatorException;
+
+  /**
+   * Annotate element using parameters.
+   * 
+   * @param element
+   *          object to be annotated
+   * @param parameters
+   *          list of parameters passed to the annotator which is expected to be
+   *          in the same order as its {@link this#parameterDefs}
+   * @throws AnnotatorException
+   *           thrown when there is a problem with annotating not related to data
+   */
+  public void annotateElement(BioEntity element, List<UserAnnotatorsParam> parameters) throws AnnotatorException {
+    annotateElement(element);
+  }
+
+  /**
+   * Returns a list of all classes that can be annotated using this annotator.
+   * 
+   * @return a list of all classes that can be annotated using this annotator
+   */
+  public List<Class<? extends BioEntity>> getValidClasses() {
+    return validClasses;
+  }
+
+  /**
+   * Returns <code>true</code> if this annotator can annotate the object given in
+   * the parameter.
+   * 
+   * @param object
+   *          object to be tested if can be annotated
+   * @return <code>true</code> if object can be annotated by this annotator,
+   *         <code>false</code> otherwise
+   */
+  public boolean isAnnotatable(BioEntity object) {
+    Class<?> clazz = object.getClass();
+    for (Class<?> validClazz : getValidClasses()) {
+      if (validClazz.isAssignableFrom(clazz)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Adds a class to list of classes that can be annotated by the annotator.
+   * 
+   * @param clazz
+   *          class to add
+   */
+  private void addValidClass(Class<? extends BioEntity> clazz) {
+    validClasses.add(clazz);
+  }
+
+  /**
+   * Returns the common name that should be presented to user.
+   * 
+   * @return the common name
+   */
+  public abstract String getCommonName();
+
+  /**
+   * Returns url to the external resource used for annotation.
+   * 
+   * @return url
+   */
+  public abstract String getUrl();
+
+  /**
+   * Provides description of the extraction process for {@link ElementAnnotator}
+   * to be used in the front end.
+   * 
+   * @return the description
+   */
+  public String getDescription() {
+    return "";
+  }
+
+  /**
+   * Provides description for {@link ElementAnnotator} and {@link MiriamType} pair
+   * to be used in the frontend.
+   * 
+   * @param mt
+   *          {@link MiriamType} annotated by this annotator.
+   * @return the description
+   */
+  public String getDescription(MiriamType mt) {
+    return "";
+  }
+
+  /**
+   * Provides description for {@link ElementAnnotator}, {@link MiriamType} and
+   * {@link MiriamRelationType} triplet to be used in the frontend.
+   * 
+   * @param mt
+   *          {@link MiriamType} annotated by this annotator
+   * @param relationType
+   *          {@link MiriamRelationType} annotated by this annotator.
+   * @return the description
+   */
+  public String getDescription(MiriamType mt, MiriamRelationType relationType) {
+    return "";
+  }
+
+  /**
+   * Returns list with definitions of the parameters available for this annotator.
+   * 
+   * @return the parameters {@link AnnotatorParamDefinition} list
+   */
+  public Collection<AnnotatorParamDefinition> getParametersDefinitions() {
+    return paramsDefs;
+  }
+
+  /**
+   * Returns <code>true</code> if this annotator can annotate the object of given
+   * class type.
+   * 
+   * @param clazz
+   *          class to be tested if can be annotated
+   * @return <code>true</code> if class can be annotated by this annotator,
+   *         <code>false</code> otherwise
+   */
+  public boolean isAnnotatable(Class<?> clazz) {
+    for (Class<?> clazz2 : validClasses) {
+      if (clazz2.isAssignableFrom(clazz)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * 
+   * @return {@link #isDefault}
+   */
+  public boolean isDefault() {
+    return isDefault;
+  }
+
+  /**
+   * Sets symbol value to the element.
+   * 
+   * @param element
+   *          element where we change data
+   * @param symbol
+   *          new symbol
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setSymbol(BioEntity element, String symbol, String prefix) {
+    if (element.getSymbol() == null || element.getSymbol().equals("") || element.getSymbol().equals(symbol)) {
+      element.setSymbol(symbol);
+    } else {
+      logger.warn(prefix + "Symbols doesn't match: \"" + symbol + "\", \"" + element.getSymbol() + "\"");
+    }
+    if (element.getName() == null || element.getName().equals("")) {
+      element.setName(symbol);
+    }
+  }
+
+  /**
+   * Sets synonyms to the element.
+   * 
+   * @param element
+   *          element where we change data
+   * @param synonyms
+   *          new synonyms list
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setSynonyms(BioEntity element, Collection<String> synonyms, String prefix) {
+    if (element.getSynonyms() == null || element.getSynonyms().size() == 0) {
+      List<String> sortedSynonyms = new ArrayList<>();
+      sortedSynonyms.addAll(synonyms);
+      Collections.sort(sortedSynonyms);
+
+      element.setSynonyms(sortedSynonyms);
+    } else {
+      logger.warn(prefix + "Synonyms don't match: \"" + synonyms + "\", \"" + element.getSynonyms() + "\"");
+    }
+  }
+
+  /**
+   * Sets name to the element.
+   * 
+   * @param element
+   *          element where we change data
+   * @param name
+   *          new name
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setFullName(Element element, String name, String prefix) {
+    if (element.getFullName() == null || element.getFullName().equals("") || element.getFullName().equals(name)) {
+      element.setFullName(name);
+    } else {
+      logger.warn(prefix + "Names doesn't match (" + getCommonName() + " annotator and current data): \"" + name
+          + "\", \"" + element.getFullName() + "\"");
+    }
+  }
+
+  /**
+   * Adds description to {@link BioEntity#getNotes()}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param description
+   *          value to set
+   */
+  protected void setDescription(BioEntity element, String description) {
+    if (description != null) {
+      if (element.getNotes() == null || element.getNotes().equals("") || element.getNotes().equals(description)) {
+        element.setNotes(description);
+      } else if (!element.getNotes().toLowerCase().contains(description.toLowerCase())) {
+        element.setNotes(element.getNotes() + "\n" + description);
+      }
+    }
+  }
+
+  /**
+   * Adds {@link MiriamType#HMDB} annotation to element.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          annotation identifier
+   */
+  protected void addHmdbMiriam(BioEntity element, String value) {
+    element.addMiriamData(createMiriamData(MiriamType.HMDB, value));
+  }
+
+  protected void addMiriam(BioEntity element, String generalIdentifier, String prefix) {
+    MiriamData md = null;
+    try {
+      md = MiriamType.getMiriamByUri(generalIdentifier);
+    } catch (InvalidArgumentException e) {
+      try {
+        md = MiriamType.getMiriamByUri("urn:miriam:" + generalIdentifier);
+      } catch (InvalidArgumentException e1) {
+        logger.warn(prefix + "Unknown miriam uri: " + generalIdentifier);
+      }
+    }
+    if (md != null && !element.getMiriamData().contains(md)) {
+      element.addMiriamData(createMiriamData(md));
+    }
+  }
+
+  /**
+   * Sets {@link CellDesignerChemical#inChI}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param prefix
+   *          prefix used in warnings
+   * @param value
+   *          value to set
+   */
+  protected void setInchi(Chemical element, String value, String prefix) {
+    if (element.getInChI() == null || element.getInChI().isEmpty() || element.getInChI().equals(value)) {
+      element.setInChI(value);
+    } else {
+      logger.warn(prefix + "InChI in db different: \"" + element.getInChI() + "\", " + value);
+    }
+
+  }
+
+  /**
+   * Sets {@link CellDesignerChemical#inChIKey}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param prefix
+   *          prefix used in warnings
+   * @param value
+   *          value to set
+   */
+  protected void setInchiKey(Chemical element, String value, String prefix) {
+    if (element.getInChIKey() == null || element.getInChIKey().equals("")) {
+      element.setInChIKey(value);
+    } else if (!element.getInChIKey().equalsIgnoreCase(value)) {
+      logger.warn(prefix + "Different inchikey for chemical: " + element.getInChIKey() + ", " + value);
+    }
+
+  }
+
+  /**
+   * Sets {@link CellDesignerChemical#smiles}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param prefix
+   *          prefix used in warnings
+   * @param value
+   *          value to set
+   */
+  protected void setSmile(Chemical element, String value, String prefix) {
+    if (element.getSmiles() == null || element.getSmiles().isEmpty() || element.getSmiles().equals(value)) {
+      element.setSmiles(value);
+    } else {
+      logger.warn(prefix + "InChI in db different: \"" + element.getSmiles() + "\", " + value);
+    }
+
+  }
+
+  /**
+   * Adds {@link MiriamType#CHEBI} annotation to element.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          annotation identifier
+   */
+  protected void addChebiMiriam(BioEntity element, String value) {
+    if (!value.startsWith("CHEBI:")) {
+      value = "CHEBI:" + value;
+    }
+    MiriamData md = createMiriamData(MiriamType.CHEBI, value);
+    if (md != null && !element.getMiriamData().contains(md)) {
+      element.addMiriamData(createMiriamData(md));
+    }
+  }
+
+  /**
+   * Sets {@link Species#charge}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          value to set
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setCharge(Species element, String value, String prefix) {
+    Integer charge = Integer.parseInt(value);
+    if (element.getCharge() == null || element.getCharge() == 0 || element.getCharge().equals(charge)) {
+      element.setCharge(Integer.valueOf(charge));
+    } else {
+      logger.warn(prefix + "Charge in db different: \"" + element.getCharge() + "\", " + charge);
+    }
+
+  }
+
+  /**
+   * Adds {@link MiriamType#PUBCHEM} annotation to element.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          annotation identifier
+   */
+  protected void addPubchemMiriam(BioEntity element, String value) {
+    element.addMiriamData(createMiriamData(MiriamType.PUBCHEM, value));
+  }
+
+  /**
+   * Adds {@link MiriamType#COG} annotation to element.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          annotation identifier
+   */
+  protected void addCogMiriam(BioEntity element, String value) {
+    element.addMiriamData(createMiriamData(MiriamType.COG, value));
+  }
+
+  /**
+   * Sets {@link Reaction#subsystem}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          value to set
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setSubsystem(Reaction element, String value, String prefix) {
+    if (element.getSubsystem() == null || element.getSubsystem().isEmpty() || element.getSubsystem().equals(value)) {
+      element.setSubsystem(value);
+    } else {
+      logger.warn(prefix + "Subsystem in db different: \"" + element.getSubsystem() + "\", " + value);
+    }
+  }
+
+  /**
+   * Adds {@link MiriamType#EC} annotation to element.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          annotation identifier
+   */
+  protected void addEcMiriam(BioEntity element, String value) {
+    element.addMiriamData(createMiriamData(MiriamType.EC, value));
+  }
+
+  /**
+   * Adds {@link MiriamType#KEGG_COMPOUND} or {@link MiriamType#KEGG_REACTION}
+   * annotation to element.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          annotation identifier
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void addKeggMiriam(BioEntity element, String value, String prefix) {
+    if (value.startsWith("C")) {
+      MiriamData md = createMiriamData(MiriamType.KEGG_COMPOUND, value);
+      element.addMiriamData(md);
+    } else if (value.startsWith("R")) {
+      MiriamData md = createMiriamData(MiriamType.KEGG_REACTION, value);
+      element.addMiriamData(md);
+    } else if (value.startsWith("K")) {
+      MiriamData md = createMiriamData(MiriamType.KEGG_ORTHOLOGY, value);
+      element.addMiriamData(md);
+    } else {
+      logger.warn(
+          prefix + "Unknown Kegg identifier type (only Kegg compounds and reactions are supported): \"" + value + "\"");
+    }
+  }
+
+  protected void addChemspider(BioEntity element, String value) {
+    MiriamData md = createMiriamData(MiriamType.CHEMSPIDER, value);
+    element.addMiriamData(md);
+  }
+
+  protected void addWikipedia(BioEntity element, String value) {
+    MiriamData md = createMiriamData(MiriamType.WIKIPEDIA, value);
+    element.addMiriamData(md);
+  }
+
+  protected void addCas(BioEntity element, String value) {
+    MiriamData md = createMiriamData(MiriamType.CAS, value);
+    element.addMiriamData(md);
+  }
+
+  /**
+   * Sets {@link BioEntity#getFormula()}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          value to set
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setFormula(BioEntity element, String value, String prefix) {
+    if (element.getFormula() == null || element.getFormula().isEmpty() || element.getFormula().equals(value)) {
+      element.setFormula(value);
+    } else {
+      logger.warn(prefix + "Formula in db different: \"" + element.getFormula() + "\", \"" + value + "\"");
+    }
+  }
+
+  /**
+   * Sets {@link BioEntity#getAbbreviation()}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          value to set
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setAbbreviation(BioEntity element, String value, String prefix) {
+    if (element.getAbbreviation() == null || element.getAbbreviation().isEmpty()
+        || element.getAbbreviation().equals(value)) {
+      element.setAbbreviation(value);
+    } else if (!element.getAbbreviation().contains(value)) {
+      logger.warn(prefix + "Abbreviation in db different: \"" + element.getAbbreviation() + "\", " + value);
+    }
+  }
+
+  /**
+   * Sets {@link Reaction#getMechanicalConfidenceScore()}.
+   * 
+   * @param element
+   *          element where annotation should be added
+   * @param value
+   *          value to set
+   * @param prefix
+   *          prefix used in warnings
+   */
+  protected void setMcs(Reaction element, String value, String prefix) {
+    if (element.getMechanicalConfidenceScore() == null || element.getMechanicalConfidenceScore() == 0
+        || element.getMechanicalConfidenceScore().toString().equals(value)) {
+      element.setMechanicalConfidenceScore(Integer.valueOf(value));
+    } else {
+      logger
+          .warn(prefix + "MCS in db different: \"" + element.getMechanicalConfidenceScore() + "\", \"" + value + "\"");
+    }
+  }
+
+  /**
+   * Sets definitions of parameters for given annotator.
+   * 
+   * @param paramDefs
+   *          definitions to be set
+   */
+  public void setParametersDefinitions(List<AnnotatorParamDefinition> paramDefs) {
+    this.paramsDefs = paramDefs;
+  }
+
+  /**
+   * Adds parameter definition to the definitions of parameters for given
+   * annotator
+   * 
+   * @param paramDef
+   *          parameter definition to be added
+   */
+  public void addParameterDefinition(AnnotatorParamDefinition paramDef) {
+    this.paramsDefs.add(paramDef);
+  }
+
+  /**
+   * Sets MiriamData.annotator to this annotator
+   * 
+   * @param md
+   *          data for which the annotator is to be set
+   */
+  private void setAnnotator(MiriamData md) {
+    md.setAnnotator(this.getClass());
+  }
+
+  /**
+   * Creates {@link MiriamData} and sets its annotator to this annotator
+   * 
+   * @return created {@link MiriamData}
+   */
+  protected MiriamData createMiriamData() {
+    MiriamData md = new MiriamData();
+    setAnnotator(md);
+    return md;
+  }
+
+  /**
+   * Creates {@link MiriamData} and sets its annotator to this annotator
+   * 
+   * @param _md
+   *          {@link MiriamData} based on which the new {@link MiriamData} should
+   *          be created
+   * @return created {@link MiriamData}
+   */
+  protected MiriamData createMiriamData(MiriamData _md) {
+    MiriamData md = new MiriamData(_md);
+    setAnnotator(md);
+    return md;
+  }
+
+  /**
+   * Creates {@link MiriamData} and sets its annotator to this annotator
+   * 
+   * @param mt
+   *          {@link MiriamType} to be set
+   * @param resource
+   *          resource to be set
+   * @return created {@link MiriamData}
+   */
+  protected MiriamData createMiriamData(MiriamType mt, String resource) {
+    MiriamData md = new MiriamData(mt, resource);
+    setAnnotator(md);
+    return md;
+  }
+
+  /**
+   * Creates {@link MiriamData} and sets its annotator to this annotator
+   * 
+   * @param relationType
+   *          {@link MiriamRelationType} to be set
+   * @param mt
+   *          {@link MiriamType} to be set
+   * @param resource
+   *          resource to be set
+   * @return created {@link MiriamData}
+   */
+  protected MiriamData createMiriamData(MiriamRelationType relationType, MiriamType mt, String resource) {
+    MiriamData md = new MiriamData(relationType, mt, resource);
+    setAnnotator(md);
+    return md;
+  }
 }
diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java
index c006d49ed4..8cf0fd072e 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java
@@ -35,244 +35,305 @@ import lcsb.mapviewer.modelutils.map.ElementUtils;
  */
 public class ReconAnnotator extends ElementAnnotator implements IExternalService {
 
-	/**
-	 * Address of annotation rest service for elements.
-	 */
-	private static final String	ELEMENT_ANNOTATION_URL_PREFIX	 = "https://vmh.uni.lu/_api/metabolites/?page_size=10000&format=json&search=";
+  /**
+   * Address of annotation rest service for elements.
+   */
+  private static final String ELEMENT_ANNOTATION_URL_PREFIX = "https://vmh.uni.lu/_api/metabolites/?page_size=10000&format=json&search=";
 
-	/**
-	 * Address of annotation rest service for reactions.
-	 */
-	private static final String	REACTION_ANNOTATION_URL_PREFIX = "https://vmh.uni.lu/_api/reactions/?page_size=10000&format=json&search=";
+  /**
+   * Address of annotation rest service for reactions.
+   */
+  private static final String REACTION_ANNOTATION_URL_PREFIX = "https://vmh.uni.lu/_api/reactions/?page_size=10000&format=json&search=";
 
-	/**
-	 * Class used for some simple operations on {@link BioEntity} elements.
-	 */
-	private ElementUtils				elementUtils									 = new ElementUtils();
+  /**
+   * Class used for some simple operations on {@link BioEntity} elements.
+   */
+  private ElementUtils elementUtils = new ElementUtils();
 
-	@Override
-	public String refreshCacheQuery(Object query) throws SourceNotAvailable {
-		String name;
-		String result = null;
-		if (query instanceof String) {
-			name = (String) query;
-			if (name.startsWith("http")) {
-				try {
-					result = getWebPageContent(name);
-				} catch (IOException e) {
-					throw new SourceNotAvailable(e);
-				}
-			} else {
-				throw new InvalidArgumentException("Don't know what to do with string \"" + query + "\"");
-			}
-		} else {
-			throw new InvalidArgumentException("Don't know what to do with class: " + query.getClass());
-		}
-		return result;
-	}
+  @Override
+  public String refreshCacheQuery(Object query) throws SourceNotAvailable {
+    String name;
+    String result = null;
+    if (query instanceof String) {
+      name = (String) query;
+      if (name.startsWith("http")) {
+        try {
+          result = getWebPageContent(name);
+        } catch (IOException e) {
+          throw new SourceNotAvailable(e);
+        }
+      } else {
+        throw new InvalidArgumentException("Don't know what to do with string \"" + query + "\"");
+      }
+    } else {
+      throw new InvalidArgumentException("Don't know what to do with class: " + query.getClass());
+    }
+    return result;
+  }
 
-	/**
-	 * Default class logger.
-	 */
-	private static Logger logger = Logger.getLogger(ReconAnnotator.class);
+  /**
+   * Default class logger.
+   */
+  private static Logger logger = Logger.getLogger(ReconAnnotator.class);
 
-	/**
-	 * Default constructor.
-	 */
-	public ReconAnnotator() {
-		super(ReconAnnotator.class, new Class[] { Chemical.class, Reaction.class }, false);
-	}
+  /**
+   * Default constructor.
+   */
+  public ReconAnnotator() {
+    super(ReconAnnotator.class, new Class[] { Chemical.class, Reaction.class }, false);
+  }
 
-	@Override
-	public ExternalServiceStatus getServiceStatus() {
-		ExternalServiceStatus status = new ExternalServiceStatus(getCommonName(), getUrl());
+  @Override
+  public ExternalServiceStatus getServiceStatus() {
+    ExternalServiceStatus status = new ExternalServiceStatus(getCommonName(), getUrl());
 
-		GeneralCacheInterface cacheCopy = getCache();
-		this.setCache(null);
-		EventStorageLoggerAppender appender = new EventStorageLoggerAppender();
-		Logger.getRootLogger().addAppender(appender);
-		try {
-			SimpleMolecule smallMoleculeAlias = new SimpleMolecule("some_id");
-			smallMoleculeAlias.setName("h2o");
-			annotateElement(smallMoleculeAlias);
-			status.setStatus(ExternalServiceStatusType.OK);
-			if (smallMoleculeAlias.getMiriamData().size() == 0) {
-				status.setStatus(ExternalServiceStatusType.CHANGED);
-			} else if (appender.getWarnings().size() > 0) {
-				status.setStatus(ExternalServiceStatusType.CHANGED);
-			}
-		} catch (Exception e) {
-			logger.error(status.getName() + " is down", e);
-			status.setStatus(ExternalServiceStatusType.DOWN);
-		}
-		Logger.getRootLogger().removeAppender(appender);
-		this.setCache(cacheCopy);
-		return status;
-	}
+    GeneralCacheInterface cacheCopy = getCache();
+    this.setCache(null);
+    EventStorageLoggerAppender appender = new EventStorageLoggerAppender();
+    Logger.getRootLogger().addAppender(appender);
+    try {
+      SimpleMolecule smallMoleculeAlias = new SimpleMolecule("some_id");
+      smallMoleculeAlias.setName("h2o");
+      annotateElement(smallMoleculeAlias);
+      status.setStatus(ExternalServiceStatusType.OK);
+      if (smallMoleculeAlias.getMiriamData().size() == 0) {
+        status.setStatus(ExternalServiceStatusType.CHANGED);
+      } else if (appender.getWarnings().size() > 0) {
+        status.setStatus(ExternalServiceStatusType.CHANGED);
+      }
+    } catch (Exception e) {
+      logger.error(status.getName() + " is down", e);
+      status.setStatus(ExternalServiceStatusType.DOWN);
+    }
+    Logger.getRootLogger().removeAppender(appender);
+    this.setCache(cacheCopy);
+    return status;
+  }
 
-	@Override
-	public void annotateElement(BioEntity annotatedObject) throws AnnotatorException {
-		if (isAnnotatable(annotatedObject)) {
-			String id = annotatedObject.getAbbreviation();
-			if (id == null || id.isEmpty()) {
-				id = annotatedObject.getName();
-			}
-			if (id.indexOf("[") > 0) {
-				id = id.substring(0, id.indexOf("["));
-			}
-			if (id.indexOf(" ") >= 0) {
-				String[] tmp = id.split(" ");
-				id = tmp[tmp.length - 1];
-			}
-			String url = null;
-			if (annotatedObject instanceof Element) {
-				url = ELEMENT_ANNOTATION_URL_PREFIX + id;
-			} else if (annotatedObject instanceof Reaction) {
-				url = REACTION_ANNOTATION_URL_PREFIX + id;
-			} else {
-				logger.warn("Unknown class type: " + annotatedObject.getClass());
-				return;
-			}
-			try {
-				String content = getWebPageContent(url);
+  @Override
+  public void annotateElement(BioEntity annotatedObject) throws AnnotatorException {
+    if (isAnnotatable(annotatedObject)) {
+      String id = annotatedObject.getAbbreviation();
+      if (id == null || id.isEmpty()) {
+        id = annotatedObject.getName();
+      }
+      if (id.indexOf("[") > 0) {
+        id = id.substring(0, id.indexOf("["));
+      }
+      if (id.indexOf(" ") >= 0) {
+        String[] tmp = id.split(" ");
+        id = tmp[tmp.length - 1];
+      }
+      String url = null;
+      if (annotatedObject instanceof Element) {
+        url = ELEMENT_ANNOTATION_URL_PREFIX + id;
+      } else if (annotatedObject instanceof Reaction) {
+        url = REACTION_ANNOTATION_URL_PREFIX + id;
+      } else {
+        logger.warn("Unknown class type: " + annotatedObject.getClass());
+        return;
+      }
+      try {
+        String content = getWebPageContent(url);
 
-				String prefix = elementUtils.getElementTag(annotatedObject, this);
-				if (!content.isEmpty()) {
+        String prefix = elementUtils.getElementTag(annotatedObject, this);
+        if (!content.isEmpty()) {
 
-					JsonElement jelement = new JsonParser().parse(content);
-					JsonObject jobject = jelement.getAsJsonObject();
-					if (jobject.get("results").getAsJsonArray().size() > 0) {
-						jobject = jobject.get("results").getAsJsonArray().get(0).getAsJsonObject();
+          JsonElement jelement = new JsonParser().parse(content);
+          JsonObject jobject = jelement.getAsJsonObject();
+          if (jobject.get("results").getAsJsonArray().size() > 0) {
+            jobject = jobject.get("results").getAsJsonArray().get(0).getAsJsonObject();
 
-						for (Entry<String, JsonElement> entry : jobject.entrySet()) {
-							String key = entry.getKey();
-							String value = null;
-							if (!entry.getValue().isJsonNull()) {
-								// if (entry.getValue().isJsonPrimitive()) {
-								value = entry.getValue().getAsString().trim();
-							}
-							if (value == null || value.isEmpty()) {
-								continue;
-							}
+            for (Entry<String, JsonElement> entry : jobject.entrySet()) {
+              String key = entry.getKey();
+              String value = null;
+              if (!entry.getValue().isJsonNull()) {
+                // if (entry.getValue().isJsonPrimitive()) {
+                value = entry.getValue().getAsString().trim();
+              }
+              if (value == null || value.isEmpty()) {
+                continue;
+              }
 
-							boolean unknown = false;
-							if (key.equals("url")) {
-								continue;
-							} else if (key.equals("rxn_id")) {
-								continue;
-							} else if (key.equals("abbreviation")) {
-								setAbbreviation(annotatedObject, value, prefix);
-							} else if (key.equals("description")) {
-								setDescription(annotatedObject, value);
-							} else if (key.equals("formula")) {
-								setFormula(annotatedObject, value, prefix);
-							} else if (key.equals("reversible")) {
-								continue;
-							} else if (key.equals("mcs")) {
-								if (annotatedObject instanceof Reaction) {
-									setMcs((Reaction) annotatedObject, value, prefix);
-								} else {
-									unknown = true;
-								}
-							} else if (key.equals("notes")) {
-								setDescription(annotatedObject, value);
-							} else if (key.equals("ecnumber")) {
-								addEcMiriam(annotatedObject, value);
-							} else if (key.equals("ref")) {
-								continue;
-							} else if (key.equals("lastModified")) {
-								continue;
-							} else if (key.equals("met_id")) {
-								continue;
-							} else if (key.equals("csecoida")) {
-								continue;
-							} else if (key.equals("chargedFormula")) {
-								setFormula(annotatedObject, value, prefix);
-							} else if (key.equals("charge")) {
-								if (annotatedObject instanceof Species) {
-									setCharge((Species) annotatedObject, value, prefix);
-								} else {
-									unknown = true;
-								}
-							} else if (key.equals("inchiString")) {
-								if (annotatedObject instanceof Chemical) {
-									setInchi((Chemical) annotatedObject, value, prefix);
-								} else {
-									unknown = true;
-								}
-							} else if (key.equals("cheBlId")) {
-								addChebiMiriam(annotatedObject, value);
-							} else if (key.equals("subsystem")) {
-								if (annotatedObject instanceof Reaction) {
-									setSubsystem((Reaction) annotatedObject, value, prefix);
-								} else {
-									unknown = true;
-								}
-							} else if (key.equals("keggId")) {
-								addKeggMiriam(annotatedObject, value, prefix);
-							} else if (key.equals("fullName")) {
-								if (annotatedObject instanceof Element) {
-									setFullName((Element) annotatedObject, value, prefix);
-								} else {
-									unknown = true;
-								}
-							} else if (key.equals("keggorthology")) {
-								addKeggMiriam(annotatedObject, value, prefix);
-							} else if (key.equals("pubChemId")) {
-								addPubchemMiriam(annotatedObject, value);
-							} else if (key.equals("hmdb")) {
-								addHmdbMiriam(annotatedObject, value);
-							} else if (key.equals("cog")) {
-								addCogMiriam(annotatedObject, value);
-							} else if (key.equals("synonyms")) {
-								List<String> synonyms = new ArrayList<>();
-								for (String str : value.split(",")) {
-									synonyms.add(str);
-								}
-								setSynonyms(annotatedObject, synonyms, prefix);
-							} else if (key.equals("pdmapName")) {
-								// for now we skip it...
-								continue;
-							} else if (key.equals("reconMap")) {
-								// for now we don't handle it
-								continue;
-							} else {
-								unknown = true;
-							}
-							if (unknown) {
-								logger.warn(prefix + "Unknown field in recon annotation: \"" + key + "\" (value: " + value + ")");
-							}
-						}
-					} else {
-						logger.warn(prefix + "No recon annotations \"" + id + "\"");
-					}
-				} else {
-					logger.warn(prefix + "No recon annotations \"" + id + "\"");
-				}
-			} catch (IOException e) {
-				throw new AnnotatorException(e);
-			}
-		}
-	}
+              boolean unknown = false;
+              if (key.equals("url")) {
+                continue;
+              } else if (key.equals("rxn_id")) {
+                continue;
+              } else if (key.equals("abbreviation")) {
+                setAbbreviation(annotatedObject, value, prefix);
+              } else if (key.equals("description")) {
+                setDescription(annotatedObject, value);
+              } else if (key.equals("formula")) {
+                setFormula(annotatedObject, value, prefix);
+              } else if (key.equals("reversible")) {
+                continue;
+              } else if (key.equals("mcs")) {
+                if (annotatedObject instanceof Reaction) {
+                  setMcs((Reaction) annotatedObject, value, prefix);
+                } else {
+                  unknown = true;
+                }
+              } else if (key.equals("notes")) {
+                setDescription(annotatedObject, value);
+              } else if (key.equals("ecnumber")) {
+                addEcMiriam(annotatedObject, value);
+              } else if (key.equals("ref")) {
+                continue;
+              } else if (key.equals("lastModified")) {
+                continue;
+              } else if (key.equals("met_id")) {
+                continue;
+              } else if (key.equals("csecoida")) {
+                continue;
+              } else if (key.equals("chargedFormula")) {
+                setFormula(annotatedObject, value, prefix);
+              } else if (key.equals("charge")) {
+                if (annotatedObject instanceof Species) {
+                  setCharge((Species) annotatedObject, value, prefix);
+                } else {
+                  unknown = true;
+                }
+              } else if (key.equals("inchiString")) {
+                if (annotatedObject instanceof Chemical) {
+                  setInchi((Chemical) annotatedObject, value, prefix);
+                } else {
+                  unknown = true;
+                }
+              } else if (key.equals("cheBlId")) {
+                addChebiMiriam(annotatedObject, value);
+              } else if (key.equals("subsystem")) {
+                if (annotatedObject instanceof Reaction) {
+                  setSubsystem((Reaction) annotatedObject, value, prefix);
+                } else {
+                  unknown = true;
+                }
+              } else if (key.equals("keggId")) {
+                addKeggMiriam(annotatedObject, value, prefix);
+              } else if (key.equals("fullName")) {
+                if (annotatedObject instanceof Element) {
+                  setFullName((Element) annotatedObject, value, prefix);
+                } else {
+                  unknown = true;
+                }
+              } else if (key.equals("keggorthology")) {
+                addKeggMiriam(annotatedObject, value, prefix);
+              } else if (key.equals("pubChemId")) {
+                addPubchemMiriam(annotatedObject, value);
+              } else if (key.equals("hmdb")) {
+                addHmdbMiriam(annotatedObject, value);
+              } else if (key.equals("cog")) {
+                addCogMiriam(annotatedObject, value);
+              } else if (key.equals("synonyms")) {
+                List<String> synonyms = new ArrayList<>();
+                for (String str : value.split(",")) {
+                  synonyms.add(str);
+                }
+                setSynonyms(annotatedObject, synonyms, prefix);
+              } else if (key.equals("pdmapName")) {
+                // for now we skip it...
+                continue;
+              } else if (key.equals("reconMap")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("reconMap3")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("massbalance")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("isHuman")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("isMicrobe")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("iupac")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("avgmolweight")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("monoisotopicweight")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("miriam")) {
+                addMiriam(annotatedObject, value, prefix);
+              } else if (key.equals("biggId")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("lmId")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("hepatonetId")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("inchiKey")) {
+                if (annotatedObject instanceof Chemical) {
+                  setInchiKey((Chemical) annotatedObject, value, prefix);
+                }
+              } else if (key.equals("smile")) {
+                if (annotatedObject instanceof Chemical) {
+                  setSmile((Chemical) annotatedObject, value, prefix);
+                }
+              } else if (key.equals("metanetx")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("seed")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("food_db")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("chemspider")) {
+                addChemspider(annotatedObject, value);
+              } else if (key.equals("wikipedia")) {
+                addWikipedia(annotatedObject, value);
+              } else if (key.equals("metlin")) {
+                // for now we don't handle it
+                continue;
+              } else if (key.equals("casRegistry")) {
+                addCas(annotatedObject, value);
+              } else if (key.equals("epa_id")) {
+                // for now we don't handle it
+                continue;
+              } else {
+                unknown = true;
+              }
+              if (unknown) {
+                logger.warn(prefix + "Unknown field in recon annotation: \"" + key + "\" (value: " + value + ")");
+              }
+            }
+          } else {
+            logger.warn(prefix + "No recon annotations \"" + id + "\"");
+          }
+        } else {
+          logger.warn(prefix + "No recon annotations \"" + id + "\"");
+        }
+      } catch (IOException e) {
+        throw new AnnotatorException(e);
+      }
+    }
+  }
 
-	@Override
-	public String getCommonName() {
-		return "Recon annotator";
-	}
+  @Override
+  public String getCommonName() {
+    return "Recon annotator";
+  }
 
-	@Override
-	public String getUrl() {
-		return "http://humanmetabolism.org/";
-	}
+  @Override
+  public String getUrl() {
+    return "http://humanmetabolism.org/";
+  }
 
-	@Override
-	protected WebPageDownloader getWebPageDownloader() {
-		return super.getWebPageDownloader();
-	}
+  @Override
+  protected WebPageDownloader getWebPageDownloader() {
+    return super.getWebPageDownloader();
+  }
 
-	@Override
-	protected void setWebPageDownloader(WebPageDownloader webPageDownloader) {
-		super.setWebPageDownloader(webPageDownloader);
-	}
+  @Override
+  protected void setWebPageDownloader(WebPageDownloader webPageDownloader) {
+    super.setWebPageDownloader(webPageDownloader);
+  }
 
 }
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotatorTest.java
index b70fe82bdf..3fe3c8a56a 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotatorTest.java
@@ -32,320 +32,321 @@ import lcsb.mapviewer.model.map.species.SimpleMolecule;
 import lcsb.mapviewer.model.map.species.Species;
 
 public class ReconAnnotatorTest extends AnnotationTestFunctions {
-	Logger				 logger	= Logger.getLogger(ReconAnnotatorTest.class);
-	@Autowired
-	ReconAnnotator reconAnnotator;
-
-	@Before
-	public void setUp() throws Exception {
-	}
-
-	@After
-	public void tearDown() throws Exception {
-	}
-
-	@Test
-	public void testAnnotateReaction() throws Exception {
-		try {
-			Reaction reaction = new Reaction();
-			reaction.setAbbreviation("P5CRm");
-			reconAnnotator.annotateElement(reaction);
-			assertTrue("No new annotations from recon db imported", reaction.getMiriamData().size() > 0);
-			assertEquals(0, getWarnings().size());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testAnnotating_O16G2e_Reaction() throws Exception {
-		try {
-			Reaction reaction = new Reaction();
-			reaction.setName("O16G2e");
-			reconAnnotator.annotateElement(reaction);
-			assertEquals(0, getWarnings().size());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testSpeciesAnnotationWithInvalidResponse() throws Exception {
-		WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
-		GeneralCacheInterface originalCache = reconAnnotator.getCache();
-		try {
-			Ion ion = new Ion("id");
-			ion.setName("O16G2e");
-
-			// exclude first cached value
-			reconAnnotator.setCache(null);
-
-			WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
-			when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("");
-			reconAnnotator.setWebPageDownloader(mockDownloader);
-
-			reconAnnotator.annotateElement(ion);
-			assertEquals(1, getWarnings().size());
-			assertTrue(getWarnings().get(0).getMessage().toString().contains("No recon annotations"));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		} finally {
-			reconAnnotator.setWebPageDownloader(downloader);
-			reconAnnotator.setCache(originalCache);
-		}
-	}
-
-	@Test
-	public void testSpeciesAnnotationWithReactionResponse() throws Exception {
-		WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
-		GeneralCacheInterface originalCache = reconAnnotator.getCache();
-		try {
-			Ion ion = new Ion("id");
-			ion.setName("O16G2e");
-
-			// exclude first cached value
-			reconAnnotator.setCache(null);
-			
-			String response = super.readFile("testFiles/annotation/recon_reaction_response.json");
-
-			WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
-			when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn(response);
-			reconAnnotator.setWebPageDownloader(mockDownloader);
-
-			reconAnnotator.annotateElement(ion);
-			assertEquals(2, getWarnings().size());
-			assertTrue(getWarnings().get(0).getMessage().toString().contains("Unknown field"));
-			assertTrue(getWarnings().get(1).getMessage().toString().contains("Unknown field"));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		} finally {
-			reconAnnotator.setWebPageDownloader(downloader);
-			reconAnnotator.setCache(originalCache);
-		}
-	}
-
-	@Test
-	public void testReactionAnnotationWithChemicalResponse() throws Exception {
-		WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
-		GeneralCacheInterface originalCache = reconAnnotator.getCache();
-		try {
-			Reaction reaction = new Reaction();
-			reaction.setName("nad[m]");
-
-			// exclude first cached value
-			reconAnnotator.setCache(null);
-			
-			String response = super.readFile("testFiles/annotation/recon_chemical_response.json");
-
-			WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
-			when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn(response);
-			reconAnnotator.setWebPageDownloader(mockDownloader);
-
-			reconAnnotator.annotateElement(reaction);
-			assertEquals(2, getWarnings().size());
-			assertTrue(getWarnings().get(0).getMessage().toString().contains("Unknown field"));
-			assertTrue(getWarnings().get(1).getMessage().toString().contains("Unknown field"));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		} finally {
-			reconAnnotator.setWebPageDownloader(downloader);
-			reconAnnotator.setCache(originalCache);
-		}
-	}
-
-	@Test
-	public void testAnnotateUnknownElement() throws Exception {
-		try {
-			BioEntity obj = Mockito.mock(BioEntity.class);
-			when(obj.getName()).thenReturn("O16G2e");
-
-			ReconAnnotator tweakedReconAnnotator = Mockito.spy(reconAnnotator);
-			doReturn(true).when(tweakedReconAnnotator).isAnnotatable(any(BioEntity.class));
-
-			tweakedReconAnnotator.annotateElement(obj);
-			assertEquals(1, getWarnings().size());
-			assertTrue(getWarnings().get(0).getMessage().toString().contains("Unknown class type"));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testAnnotatingWithParentehesis() throws Exception {
-		try {
-			Reaction reaction = new Reaction();
-			reaction.setName("gm2_hs[g]");
-			reconAnnotator.annotateElement(reaction);
-			assertEquals(0, getWarnings().size());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testAnnotatingWithWhitespace() throws Exception {
-		try {
-			Reaction reaction = new Reaction();
-			reaction.setName("NDPK4m ");
-			reconAnnotator.annotateElement(reaction);
-			assertEquals(0, getWarnings().size());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testAnnotateElement() throws Exception {
-		try {
-			SimpleMolecule smallMolecule = new SimpleMolecule("id");
-			smallMolecule.setAbbreviation("h2o");
-			reconAnnotator.annotateElement(smallMolecule);
-			assertTrue("No new annotations from recon db imported", smallMolecule.getMiriamData().size() > 0);
-			assertEquals(0, getWarnings().size());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testAnnotateElement2() throws Exception {
-		try {
-			Species smallMolecule = new SimpleMolecule("id");
-			smallMolecule.setAbbreviation("P5CRm");
-			reconAnnotator.annotateElement(smallMolecule);
-			assertEquals(0, smallMolecule.getMiriamData().size());
-			assertFalse(getWarnings().size() == 0);
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testRefreshInvalidCacheQuery() throws Exception {
-		try {
-			reconAnnotator.refreshCacheQuery("invalid_query");
-			fail("Exception expected");
-		} catch (InvalidArgumentException e) {
-			assertTrue(e.getMessage().contains("Don't know what to do"));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testRefreshInvalidCacheQuery2() throws Exception {
-		try {
-			reconAnnotator.refreshCacheQuery(new Object());
-			fail("Exception expected");
-		} catch (InvalidArgumentException e) {
-			assertTrue(e.getMessage().contains("Don't know what to do"));
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testRefreshCacheQuery() throws Exception {
-		try {
-			String res = reconAnnotator.refreshCacheQuery("http://google.pl/");
-			assertNotNull(res);
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testStatus() throws Exception {
-		try {
-			assertEquals(ExternalServiceStatusType.OK, reconAnnotator.getServiceStatus().getStatus());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		}
-	}
-
-	@Test
-	public void testSimulateDownStatus() throws Exception {
-		WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
-		try {
-			WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
-			when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenThrow(new IOException());
-			reconAnnotator.setWebPageDownloader(mockDownloader);
-			assertEquals(ExternalServiceStatusType.DOWN, reconAnnotator.getServiceStatus().getStatus());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		} finally {
-			reconAnnotator.setWebPageDownloader(downloader);
-		}
-	}
-
-	@Test
-	public void testSimulateChangeStatus() throws Exception {
-		WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
-		try {
-			WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
-			when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("{\"results\":[{}]}");
-			reconAnnotator.setWebPageDownloader(mockDownloader);
-			assertEquals(ExternalServiceStatusType.CHANGED, reconAnnotator.getServiceStatus().getStatus());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		} finally {
-			reconAnnotator.setWebPageDownloader(downloader);
-		}
-	}
-
-	@Test
-	public void testSimulateChangeStatus2() throws Exception {
-		WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
-		try {
-			WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
-			when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("{\"results\":[{\"keggId\":\"C00001\",\"xxx\":\"yyy\"}]}");
-			reconAnnotator.setWebPageDownloader(mockDownloader);
-			assertEquals(ExternalServiceStatusType.CHANGED, reconAnnotator.getServiceStatus().getStatus());
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		} finally {
-			reconAnnotator.setWebPageDownloader(downloader);
-		}
-	}
-
-	@Test
-	public void testRefreshCacheQueryNotAvailable() throws Exception {
-		WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
-		GeneralCacheInterface originalCache = reconAnnotator.getCache();
-		try {
-			// exclude first cached value
-			reconAnnotator.setCache(null);
-
-			WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
-			when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenThrow(new IOException());
-			reconAnnotator.setWebPageDownloader(mockDownloader);
-			reconAnnotator.refreshCacheQuery("http://google.pl/");
-			fail("Exception expected");
-		} catch (SourceNotAvailable e) {
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw e;
-		} finally {
-			reconAnnotator.setWebPageDownloader(downloader);
-			reconAnnotator.setCache(originalCache);
-		}
-	}
+  Logger logger = Logger.getLogger(ReconAnnotatorTest.class);
+  @Autowired
+  ReconAnnotator reconAnnotator;
+
+  @Before
+  public void setUp() throws Exception {
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  @Test
+  public void testAnnotateReaction() throws Exception {
+    try {
+      Reaction reaction = new Reaction();
+      reaction.setAbbreviation("P5CRm");
+      reconAnnotator.annotateElement(reaction);
+      assertTrue("No new annotations from recon db imported", reaction.getMiriamData().size() > 0);
+      assertEquals(0, getWarnings().size());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testAnnotating_O16G2e_Reaction() throws Exception {
+    try {
+      Reaction reaction = new Reaction();
+      reaction.setName("O16G2e");
+      reconAnnotator.annotateElement(reaction);
+      assertEquals(0, getWarnings().size());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testSpeciesAnnotationWithInvalidResponse() throws Exception {
+    WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
+    GeneralCacheInterface originalCache = reconAnnotator.getCache();
+    try {
+      Ion ion = new Ion("id");
+      ion.setName("O16G2e");
+
+      // exclude first cached value
+      reconAnnotator.setCache(null);
+
+      WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
+      when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("");
+      reconAnnotator.setWebPageDownloader(mockDownloader);
+
+      reconAnnotator.annotateElement(ion);
+      assertEquals(1, getWarnings().size());
+      assertTrue(getWarnings().get(0).getMessage().toString().contains("No recon annotations"));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      reconAnnotator.setWebPageDownloader(downloader);
+      reconAnnotator.setCache(originalCache);
+    }
+  }
+
+  @Test
+  public void testSpeciesAnnotationWithReactionResponse() throws Exception {
+    WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
+    GeneralCacheInterface originalCache = reconAnnotator.getCache();
+    try {
+      Ion ion = new Ion("id");
+      ion.setName("O16G2e");
+
+      // exclude first cached value
+      reconAnnotator.setCache(null);
+
+      String response = super.readFile("testFiles/annotation/recon_reaction_response.json");
+
+      WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
+      when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn(response);
+      reconAnnotator.setWebPageDownloader(mockDownloader);
+
+      reconAnnotator.annotateElement(ion);
+      assertEquals(2, getWarnings().size());
+      assertTrue(getWarnings().get(0).getMessage().toString().contains("Unknown field"));
+      assertTrue(getWarnings().get(1).getMessage().toString().contains("Unknown field"));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      reconAnnotator.setWebPageDownloader(downloader);
+      reconAnnotator.setCache(originalCache);
+    }
+  }
+
+  @Test
+  public void testReactionAnnotationWithChemicalResponse() throws Exception {
+    WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
+    GeneralCacheInterface originalCache = reconAnnotator.getCache();
+    try {
+      Reaction reaction = new Reaction();
+      reaction.setName("nad[m]");
+
+      // exclude first cached value
+      reconAnnotator.setCache(null);
+
+      String response = super.readFile("testFiles/annotation/recon_chemical_response.json");
+
+      WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
+      when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn(response);
+      reconAnnotator.setWebPageDownloader(mockDownloader);
+
+      reconAnnotator.annotateElement(reaction);
+      assertEquals(2, getWarnings().size());
+      assertTrue(getWarnings().get(0).getMessage().toString().contains("Unknown field"));
+      assertTrue(getWarnings().get(1).getMessage().toString().contains("Unknown field"));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      reconAnnotator.setWebPageDownloader(downloader);
+      reconAnnotator.setCache(originalCache);
+    }
+  }
+
+  @Test
+  public void testAnnotateUnknownElement() throws Exception {
+    try {
+      BioEntity obj = Mockito.mock(BioEntity.class);
+      when(obj.getName()).thenReturn("O16G2e");
+
+      ReconAnnotator tweakedReconAnnotator = Mockito.spy(reconAnnotator);
+      doReturn(true).when(tweakedReconAnnotator).isAnnotatable(any(BioEntity.class));
+
+      tweakedReconAnnotator.annotateElement(obj);
+      assertEquals(1, getWarnings().size());
+      assertTrue(getWarnings().get(0).getMessage().toString().contains("Unknown class type"));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testAnnotatingWithParentehesis() throws Exception {
+    try {
+      Reaction reaction = new Reaction();
+      reaction.setName("gm2_hs[g]");
+      reconAnnotator.annotateElement(reaction);
+      assertEquals(0, getWarnings().size());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testAnnotatingWithWhitespace() throws Exception {
+    try {
+      Reaction reaction = new Reaction();
+      reaction.setName("NDPK4m ");
+      reconAnnotator.annotateElement(reaction);
+      assertEquals(0, getWarnings().size());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testAnnotateElement() throws Exception {
+    try {
+      SimpleMolecule smallMolecule = new SimpleMolecule("id");
+      smallMolecule.setAbbreviation("h2o");
+      reconAnnotator.annotateElement(smallMolecule);
+      assertTrue("No new annotations from recon db imported", smallMolecule.getMiriamData().size() > 0);
+      assertEquals(0, getWarnings().size());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testAnnotateElement2() throws Exception {
+    try {
+      Species smallMolecule = new SimpleMolecule("id");
+      smallMolecule.setAbbreviation("P5CRm");
+      reconAnnotator.annotateElement(smallMolecule);
+      assertEquals(0, smallMolecule.getMiriamData().size());
+      assertFalse(getWarnings().size() == 0);
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testRefreshInvalidCacheQuery() throws Exception {
+    try {
+      reconAnnotator.refreshCacheQuery("invalid_query");
+      fail("Exception expected");
+    } catch (InvalidArgumentException e) {
+      assertTrue(e.getMessage().contains("Don't know what to do"));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testRefreshInvalidCacheQuery2() throws Exception {
+    try {
+      reconAnnotator.refreshCacheQuery(new Object());
+      fail("Exception expected");
+    } catch (InvalidArgumentException e) {
+      assertTrue(e.getMessage().contains("Don't know what to do"));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testRefreshCacheQuery() throws Exception {
+    try {
+      String res = reconAnnotator.refreshCacheQuery("http://google.pl/");
+      assertNotNull(res);
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testStatus() throws Exception {
+    try {
+      assertEquals(ExternalServiceStatusType.OK, reconAnnotator.getServiceStatus().getStatus());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testSimulateDownStatus() throws Exception {
+    WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
+    try {
+      WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
+      when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenThrow(new IOException());
+      reconAnnotator.setWebPageDownloader(mockDownloader);
+      assertEquals(ExternalServiceStatusType.DOWN, reconAnnotator.getServiceStatus().getStatus());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      reconAnnotator.setWebPageDownloader(downloader);
+    }
+  }
+
+  @Test
+  public void testSimulateChangeStatus() throws Exception {
+    WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
+    try {
+      WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
+      when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("{\"results\":[{}]}");
+      reconAnnotator.setWebPageDownloader(mockDownloader);
+      assertEquals(ExternalServiceStatusType.CHANGED, reconAnnotator.getServiceStatus().getStatus());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      reconAnnotator.setWebPageDownloader(downloader);
+    }
+  }
+
+  @Test
+  public void testSimulateChangeStatus2() throws Exception {
+    WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
+    try {
+      WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
+      when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString()))
+          .thenReturn("{\"results\":[{\"keggId\":\"C00001\",\"xxx\":\"yyy\"}]}");
+      reconAnnotator.setWebPageDownloader(mockDownloader);
+      assertEquals(ExternalServiceStatusType.CHANGED, reconAnnotator.getServiceStatus().getStatus());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      reconAnnotator.setWebPageDownloader(downloader);
+    }
+  }
+
+  @Test
+  public void testRefreshCacheQueryNotAvailable() throws Exception {
+    WebPageDownloader downloader = reconAnnotator.getWebPageDownloader();
+    GeneralCacheInterface originalCache = reconAnnotator.getCache();
+    try {
+      // exclude first cached value
+      reconAnnotator.setCache(null);
+
+      WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
+      when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenThrow(new IOException());
+      reconAnnotator.setWebPageDownloader(mockDownloader);
+      reconAnnotator.refreshCacheQuery("http://google.pl/");
+      fail("Exception expected");
+    } catch (SourceNotAvailable e) {
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      reconAnnotator.setWebPageDownloader(downloader);
+      reconAnnotator.setCache(originalCache);
+    }
+  }
 
 }
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java b/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java
index b39394717c..df27800781 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java
@@ -674,7 +674,7 @@ public enum MiriamType {
    * 
    * @param generalIdentifier
    *          identifier in the format NAME:IDENTIFIER. Where NAME is the name
-   *          from {@link MiriamType#commonName} and IDENTIFIER is reasource
+   *          from {@link MiriamType#commonName} and IDENTIFIER is resource
    *          identifier.
    * @return {@link MiriamData} representing generalIdentifier, when identifier is
    *         invalid InvalidArgumentException is thrown
-- 
GitLab