commit ba05f7dc249b2e7d4ab569de33a5b02e16d0b35e
Author: Tomáš Šimandl <tomas.simandl@gmail.com>
Date:   Wed Aug 8 15:45:05 2018 +0200

    Modified backend to accept graph and configuration in json format instead of jar files + added filters

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8ed6163
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+sources/.idea/
+sources/build/
+sources/WebContent/node_modules/
diff --git a/sources/WebContent/WEB-INF/web.xml b/sources/WebContent/WEB-INF/web.xml
index 8c94a72..41b64a4 100644
--- a/sources/WebContent/WEB-INF/web.xml
+++ b/sources/WebContent/WEB-INF/web.xml
@@ -17,7 +17,7 @@
 	</context-param>
 	<context-param>
 		<param-name>DbPsw</param-name>
-		<param-value></param-value>
+		<param-value>NULL</param-value>
 	</context-param>
 	<context-param>
 		<param-name>HOME_URL</param-name>
@@ -26,11 +26,11 @@
 	</context-param>
 	<context-param>
 		<param-name>storageLocation</param-name>
-		<param-value>C:\Users\adnuk\Documents\aswi\uloziste</param-value>
+		<param-value>C:\Users\Tomas\Documents\imiger\storage</param-value>
 	</context-param>
 	<context-param>
-		<param-name>crceApiBase</param-name>
-		<param-value>http://localhost:8081/rest/v2</param-value>
+		<param-name>configLocation</param-name>
+		<param-value>C:\Users\Tomas\Documents\imiger\config</param-value>
 	</context-param>
 
 	<context-param>
diff --git a/sources/dist/cocaex-compatibility.war b/sources/dist/cocaex-compatibility.war
index 7ad15e5..f1ffcc5 100644
Binary files a/sources/dist/cocaex-compatibility.war and b/sources/dist/cocaex-compatibility.war differ
diff --git a/sources/src/cz/zcu/kiv/offscreen/AttributeType.java b/sources/src/cz/zcu/kiv/offscreen/AttributeType.java
new file mode 100644
index 0000000..f1ca20f
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/AttributeType.java
@@ -0,0 +1,23 @@
+package cz.zcu.kiv.offscreen;
+
+import cz.zcu.kiv.offscreen.graph.GraphManager;
+
+public class AttributeType {
+    public String name;
+    public GraphManager.AttributeDataType dataType;
+    public String text;
+
+    public AttributeType(String name, GraphManager.AttributeDataType dataType, String text) {
+        this.name = name;
+        this.dataType = dataType;
+        this.text = text;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public GraphManager.AttributeDataType getDataType() {
+        return dataType;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/api/EdgeInterface.java b/sources/src/cz/zcu/kiv/offscreen/api/EdgeInterface.java
index 93e5d94..c29862e 100644
--- a/sources/src/cz/zcu/kiv/offscreen/api/EdgeInterface.java
+++ b/sources/src/cz/zcu/kiv/offscreen/api/EdgeInterface.java
@@ -4,6 +4,10 @@
  */
 package cz.zcu.kiv.offscreen.api;
 
+import cz.zcu.kiv.offscreen.graph.SubedgeInfo;
+
+import java.util.List;
+
 /**
  *
  * @author Jindra Pavlíková <jindra.pav2@seznam.cz>
@@ -15,4 +19,8 @@ public interface EdgeInterface {
     public String getTo();
 
     public int getId();
+
+    public List<SubedgeInfo> getSubedgeInfo();
+
+    public void setSubedgeInfo(List<SubedgeInfo> subedgeInfo);
 }
diff --git a/sources/src/cz/zcu/kiv/offscreen/api/GraphInterface.java b/sources/src/cz/zcu/kiv/offscreen/api/GraphInterface.java
index 1464552..c00c77d 100644
--- a/sources/src/cz/zcu/kiv/offscreen/api/GraphInterface.java
+++ b/sources/src/cz/zcu/kiv/offscreen/api/GraphInterface.java
@@ -4,6 +4,10 @@
  */
 package cz.zcu.kiv.offscreen.api;
 
+import cz.zcu.kiv.offscreen.AttributeType;
+import cz.zcu.kiv.offscreen.graph.EdgeArchetype;
+import cz.zcu.kiv.offscreen.graph.VertexArchetype;
+
 import java.util.List;
 import java.util.Map;
 
@@ -17,5 +21,16 @@ public interface GraphInterface {
     public void addVertex(String name, VertexInterface vertex);
     public Map<String, VertexInterface> getVertices();
     public List<EdgeInterface> getEdges();
-    
+    public List<VertexArchetype>  getVertexArchetypes();
+    public List<EdgeArchetype> getEdgeArchetypes();
+    public void setVertexArchetypes(List<VertexArchetype> vertexArchetypes);
+    public void setEdgeArchetypes(List<EdgeArchetype> edgeArchetypes);
+    public void setAttributeTypes(List<AttributeType> attributeTypes);
+    public void setPossibleEnumValues(Map<Integer, List<String>> possibleEnumValues);
+    public List<AttributeType> getAttributeTypes();
+    public Map<String, List<String>> getPossibleEnumValues();
+    void setArchetypeIcons(Map<String, String> archetypeIcons);
+    Map<String, String> getArchetypeIcons();
+    List<Integer> getDefaultGroupArchetypes();
+    void setDefaultGroupArchetypes(List<Integer> defaultGroupArchetypes);
 }
diff --git a/sources/src/cz/zcu/kiv/offscreen/api/VertexInterface.java b/sources/src/cz/zcu/kiv/offscreen/api/VertexInterface.java
index ccaeea1..1254e68 100644
--- a/sources/src/cz/zcu/kiv/offscreen/api/VertexInterface.java
+++ b/sources/src/cz/zcu/kiv/offscreen/api/VertexInterface.java
@@ -26,4 +26,11 @@ public interface VertexInterface {
 
 	public void setImportedPackages(List<String> importedPackages);
 
+	public int getArchetype();
+
+	public void setArchetype(int archetype);
+
+	public void setAttributes(List<String[]> attributes);
+
+	public List<String[]> getAttributes();
 }
diff --git a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexData.java b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexData.java
index 9954476..ffe04e8 100644
--- a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexData.java
+++ b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexData.java
@@ -1,46 +1,46 @@
-/**
- * 
- */
-package cz.zcu.kiv.offscreen.data.efpportal;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 
- * Representation of EFPPortal's connections . A connection consists of a provided and required features.
- * 
- * @author Jiri Loudil
- *
- */
-public class CocaexData {
-	/**
-	 * Map of all provided features.
-	 */
-	private Map<String, CocaexDataFeature> providedFeatures;
-	
-	/**
-	 * Map of all required features.
-	 */
-	private Map<String, CocaexDataFeature> requiredFeatures;
-	
-	public CocaexData() {
-		this.providedFeatures = new HashMap<String, CocaexDataFeature>();
-		this.requiredFeatures = new HashMap<String, CocaexDataFeature>();
-	}
-
-	/**
-	 * @return the providedFeatures
-	 */
-	public Map<String, CocaexDataFeature> getProvidedFeatures() {
-		return providedFeatures;
-	}
-
-	/**
-	 * @return the importedFeatures
-	 */
-	public Map<String, CocaexDataFeature> getRequiredFeatures() {
-		return requiredFeatures;
-	}
-
-}
+///**
+// *
+// */
+//package cz.zcu.kiv.offscreen.data.efpportal;
+//
+//import java.util.HashMap;
+//import java.util.Map;
+//
+///**
+// *
+// * Representation of EFPPortal's connections . A connection consists of a provided and required features.
+// *
+// * @author Jiri Loudil
+// *
+// */
+//public class CocaexData {
+//	/**
+//	 * Map of all provided features.
+//	 */
+//	private Map<String, CocaexDataFeature> providedFeatures;
+//
+//	/**
+//	 * Map of all required features.
+//	 */
+//	private Map<String, CocaexDataFeature> requiredFeatures;
+//
+//	public CocaexData() {
+//		this.providedFeatures = new HashMap<String, CocaexDataFeature>();
+//		this.requiredFeatures = new HashMap<String, CocaexDataFeature>();
+//	}
+//
+//	/**
+//	 * @return the providedFeatures
+//	 */
+//	public Map<String, CocaexDataFeature> getProvidedFeatures() {
+//		return providedFeatures;
+//	}
+//
+//	/**
+//	 * @return the importedFeatures
+//	 */
+//	public Map<String, CocaexDataFeature> getRequiredFeatures() {
+//		return requiredFeatures;
+//	}
+//
+//}
diff --git a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataEfp.java b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataEfp.java
index 1fc448a..80f677f 100644
--- a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataEfp.java
+++ b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataEfp.java
@@ -1,69 +1,69 @@
-package cz.zcu.kiv.offscreen.data.efpportal;
-
-import cz.zcu.kiv.efps.comparator.result.EfpEvalResult.MatchingResult;
-import cz.zcu.kiv.efps.types.datatypes.EfpValueType;
-
-/**
- * Holds EFP's data.
- * 
- * @author Jiri Loudil
- *
- */
-public class CocaexDataEfp {
-	private String efpName;
-	private String efpValueTypeName;
-	private EfpValueType efpValue;
-	private MatchingResult typeError;
-	
-	/**
-	 * @return the efpName
-	 */
-	public String getEfpName() {
-		return efpName;
-	}
-	/**
-	 * @param efpName the efpName to set
-	 */
-	public void setEfpName(String efpName) {
-		this.efpName = efpName;
-	}
-	/**
-	 * @return the efpValueTypeName
-	 */
-	public String getEfpValueTypeName() {
-		return efpValueTypeName;
-	}
-	/**
-	 * @param efpValueTypeName the efpValueTypeName to set
-	 */
-	public void setEfpValueTypeName(String efpValueTypeName) {
-		this.efpValueTypeName = efpValueTypeName;
-	}
-	/**
-	 * @return the efpValue
-	 */
-	public EfpValueType getEfpValue() {
-		return efpValue;
-	}
-	/**
-	 * @param efpValue the efpValue to set
-	 */
-	public void setEfpValue(EfpValueType efpValue) {
-		this.efpValue = efpValue;
-	}
-
-	/**
-	 * @return the typeError
-	 */
-	public MatchingResult getTypeError() {
-		return typeError;
-	}
-
-	/**
-	 * @param typeError the typeError to set
-	 */
-	public void setTypeError(MatchingResult typeError) {
-		this.typeError = typeError;
-	}
-	
-}
\ No newline at end of file
+//package cz.zcu.kiv.offscreen.data.efpportal;
+//
+//import cz.zcu.kiv.efps.comparator.result.EfpEvalResult.MatchingResult;
+//import cz.zcu.kiv.efps.types.datatypes.EfpValueType;
+//
+///**
+// * Holds EFP's data.
+// *
+// * @author Jiri Loudil
+// *
+// */
+//public class CocaexDataEfp {
+//	private String efpName;
+//	private String efpValueTypeName;
+//	private EfpValueType efpValue;
+//	private MatchingResult typeError;
+//
+//	/**
+//	 * @return the efpName
+//	 */
+//	public String getEfpName() {
+//		return efpName;
+//	}
+//	/**
+//	 * @param efpName the efpName to set
+//	 */
+//	public void setEfpName(String efpName) {
+//		this.efpName = efpName;
+//	}
+//	/**
+//	 * @return the efpValueTypeName
+//	 */
+//	public String getEfpValueTypeName() {
+//		return efpValueTypeName;
+//	}
+//	/**
+//	 * @param efpValueTypeName the efpValueTypeName to set
+//	 */
+//	public void setEfpValueTypeName(String efpValueTypeName) {
+//		this.efpValueTypeName = efpValueTypeName;
+//	}
+//	/**
+//	 * @return the efpValue
+//	 */
+//	public EfpValueType getEfpValue() {
+//		return efpValue;
+//	}
+//	/**
+//	 * @param efpValue the efpValue to set
+//	 */
+//	public void setEfpValue(EfpValueType efpValue) {
+//		this.efpValue = efpValue;
+//	}
+//
+//	/**
+//	 * @return the typeError
+//	 */
+//	public MatchingResult getTypeError() {
+//		return typeError;
+//	}
+//
+//	/**
+//	 * @param typeError the typeError to set
+//	 */
+//	public void setTypeError(MatchingResult typeError) {
+//		this.typeError = typeError;
+//	}
+//
+//}
\ No newline at end of file
diff --git a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataFeature.java b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataFeature.java
index 37fdd66..d3870c2 100644
--- a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataFeature.java
+++ b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexDataFeature.java
@@ -1,33 +1,33 @@
-package cz.zcu.kiv.offscreen.data.efpportal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Holds feature's data.
- * 
- * @author Jiri Loudil
- *
- */
-public class CocaexDataFeature {
-	private List<CocaexDataEfp> efps;
-
-	public CocaexDataFeature() {
-		this.efps = new ArrayList<CocaexDataEfp>();
-	}
-
-	/**
-	 * @return the efps
-	 */
-	public List<CocaexDataEfp> getEfps() {
-		return efps;
-	}
-
-	/**
-	 * @param efps the efps to set
-	 */
-	public void setEfps(List<CocaexDataEfp> efps) {
-		this.efps = efps;
-	}
-
-}
\ No newline at end of file
+//package cz.zcu.kiv.offscreen.data.efpportal;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//
+///**
+// * Holds feature's data.
+// *
+// * @author Jiri Loudil
+// *
+// */
+//public class CocaexDataFeature {
+//	private List<CocaexDataEfp> efps;
+//
+//	public CocaexDataFeature() {
+//		this.efps = new ArrayList<CocaexDataEfp>();
+//	}
+//
+//	/**
+//	 * @return the efps
+//	 */
+//	public List<CocaexDataEfp> getEfps() {
+//		return efps;
+//	}
+//
+//	/**
+//	 * @param efps the efps to set
+//	 */
+//	public void setEfps(List<CocaexDataEfp> efps) {
+//		this.efps = efps;
+//	}
+//
+//}
\ No newline at end of file
diff --git a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexWrapper.java b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexWrapper.java
index 70ff5db..32fdd62 100644
--- a/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexWrapper.java
+++ b/sources/src/cz/zcu/kiv/offscreen/data/efpportal/CocaexWrapper.java
@@ -1,66 +1,66 @@
-package cz.zcu.kiv.offscreen.data.efpportal;
-
-import java.util.Map;
-
-/**
- * 
- * EFPPortal export data wrapper. Contains mappings for feature connection names and EFPs names.
- * 
- * @author Jiri Loudil
- *
- */
-public class CocaexWrapper {
-	/**
-	 * Feature names mapping.
-	 */
-	private Map<String, String> featureMappings;
-	
-	/**
-	 * EFPs name s mapping.
-	 */
-	private Map<String, String> efpMappings;
-	
-	/**
-	 * EFPPortal data with IDs instead of names for EFPs and Features.
-	 */
-	private Map<String, CocaexData> data;
-	
-	/**
-	 * @return the featureMappings
-	 */
-	public Map<String, String> getFeatureMappings() {
-		return featureMappings;
-	}
-	/**
-	 * @param featureMappings the featureMappings to set
-	 */
-	public void setFeatureMappings(Map<String, String> featureMappings) {
-		this.featureMappings = featureMappings;
-	}
-	/**
-	 * @return the efpMappings
-	 */
-	public Map<String, String> getEfpMappings() {
-		return efpMappings;
-	}
-	/**
-	 * @param efpMappings the efpMappings to set
-	 */
-	public void setEfpMappings(Map<String, String> efpMappings) {
-		this.efpMappings = efpMappings;
-	}
-	/**
-	 * @return the data
-	 */
-	public Map<String, CocaexData> getData() {
-		return data;
-	}
-	/**
-	 * @param data the data to set
-	 */
-	public void setData(Map<String, CocaexData> data) {
-		this.data = data;
-	}
-	
-	
-}
+//package cz.zcu.kiv.offscreen.data.efpportal;
+//
+//import java.util.Map;
+//
+///**
+// *
+// * EFPPortal export data wrapper. Contains mappings for feature connection names and EFPs names.
+// *
+// * @author Jiri Loudil
+// *
+// */
+//public class CocaexWrapper {
+//	/**
+//	 * Feature names mapping.
+//	 */
+//	private Map<String, String> featureMappings;
+//
+//	/**
+//	 * EFPs name s mapping.
+//	 */
+//	private Map<String, String> efpMappings;
+//
+//	/**
+//	 * EFPPortal data with IDs instead of names for EFPs and Features.
+//	 */
+//	private Map<String, CocaexData> data;
+//
+//	/**
+//	 * @return the featureMappings
+//	 */
+//	public Map<String, String> getFeatureMappings() {
+//		return featureMappings;
+//	}
+//	/**
+//	 * @param featureMappings the featureMappings to set
+//	 */
+//	public void setFeatureMappings(Map<String, String> featureMappings) {
+//		this.featureMappings = featureMappings;
+//	}
+//	/**
+//	 * @return the efpMappings
+//	 */
+//	public Map<String, String> getEfpMappings() {
+//		return efpMappings;
+//	}
+//	/**
+//	 * @param efpMappings the efpMappings to set
+//	 */
+//	public void setEfpMappings(Map<String, String> efpMappings) {
+//		this.efpMappings = efpMappings;
+//	}
+//	/**
+//	 * @return the data
+//	 */
+//	public Map<String, CocaexData> getData() {
+//		return data;
+//	}
+//	/**
+//	 * @param data the data to set
+//	 */
+//	public void setData(Map<String, CocaexData> data) {
+//		this.data = data;
+//	}
+//
+//
+//}
diff --git a/sources/src/cz/zcu/kiv/offscreen/efp/utils/JsonTransformer.java b/sources/src/cz/zcu/kiv/offscreen/efp/utils/JsonTransformer.java
index 2c0335a..1d33aac 100644
--- a/sources/src/cz/zcu/kiv/offscreen/efp/utils/JsonTransformer.java
+++ b/sources/src/cz/zcu/kiv/offscreen/efp/utils/JsonTransformer.java
@@ -1,101 +1,101 @@
-package cz.zcu.kiv.offscreen.efp.utils;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.zip.GZIPInputStream;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.log4j.Logger;
-
-import net.sf.json.JSONObject;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.io.IOUtils;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import cz.zcu.kiv.efps.types.datatypes.EfpValueType;
-import cz.zcu.kiv.efps.types.serialisation.json.EfpValueTypeAdapter;
-import cz.zcu.kiv.offscreen.api.GraphInterface;
-import cz.zcu.kiv.offscreen.data.efpportal.CocaexWrapper;
-import cz.zcu.kiv.offscreen.graph.GraphExport;
-import cz.zcu.kiv.offscreen.graph.creator.EfpGraphTransfomer;
-
-/**
- * 
- * Transofma and decompress tools for incoming JSON.
- * 
- * @author Jiri Loudil
- *
- */
-public class JsonTransformer {
-	private Logger logger = Logger.getLogger(JsonTransformer.class);
-
-	/**
-	 * 
-	 * Deserialize input JSON and transform to graph JSON.
-	 * 
-	 * @param inputJSON
-	 * @param request
-	 * @return
-	 * @throws IOException
-	 */
-	public String transformInputJSONToGraphJSON(String inputJSON,
-			HttpServletRequest request) throws IOException {
-		CocaexWrapper efpResults;
-
-		GsonBuilder gsonBuilder = new GsonBuilder();
-		// JSON deserializing adapter provided for EFP type classes
-		gsonBuilder.registerTypeAdapter(EfpValueType.class,
-				new EfpValueTypeAdapter());
-		// JSON deserializing adapter for the Wrapper class
-		gsonBuilder.registerTypeAdapter(CocaexWrapper.class,
-				new WrapperDeserializer());
-		Gson gson = gsonBuilder.create();
-
-		// decode + unzip received data
-		String data = decompress(inputJSON);
-
-		// deserialize using deserializer adapters
-		efpResults = gson.fromJson(data, CocaexWrapper.class);
-
-		request.setAttribute("efpPortalEfpNames", efpResults.getEfpMappings());
-
-		// transform received data to readable graph form
-		EfpGraphTransfomer transformer = new EfpGraphTransfomer(efpResults);
-		GraphInterface graph = transformer.transform();
-		GraphExport export = new GraphExport(graph);
-
-		// transform graph to JSON
-		JSONObject o = JSONObject.fromObject(export);
-
-		return o.toString();
-	}
-
-	/**
-	 * Decode and unzip a Base64 encoded GZIPed string.
-	 * 
-	 * @param input
-	 * @return
-	 * @throws IOException
-	 */
-	private String decompress(String input) throws IOException {
-		logger.trace("ENTRY");
-		String result = null;
-
-		byte[] bytes = Base64.decodeBase64(input);
-		GZIPInputStream zi = null;
-		try {
-			zi = new GZIPInputStream(new ByteArrayInputStream(bytes));
-			result = IOUtils.toString(zi);
-		} finally {
-			IOUtils.closeQuietly(zi);
-		}
-		logger.trace("EXIT");
-
-		return result;
-	}
-
-}
+//package cz.zcu.kiv.offscreen.efp.utils;
+//
+//import java.io.ByteArrayInputStream;
+//import java.io.IOException;
+//import java.util.zip.GZIPInputStream;
+//
+//import javax.servlet.http.HttpServletRequest;
+//
+//import org.apache.log4j.Logger;
+//
+//import net.sf.json.JSONObject;
+//
+//import org.apache.commons.codec.binary.Base64;
+//import org.apache.commons.io.IOUtils;
+//
+//import com.google.gson.Gson;
+//import com.google.gson.GsonBuilder;
+//
+//import cz.zcu.kiv.efps.types.datatypes.EfpValueType;
+//import cz.zcu.kiv.efps.types.serialisation.json.EfpValueTypeAdapter;
+//import cz.zcu.kiv.offscreen.api.GraphInterface;
+//import cz.zcu.kiv.offscreen.data.efpportal.CocaexWrapper;
+//import cz.zcu.kiv.offscreen.graph.GraphExport;
+//import cz.zcu.kiv.offscreen.graph.creator.EfpGraphTransfomer;
+//
+///**
+// *
+// * Transofma and decompress tools for incoming JSON.
+// *
+// * @author Jiri Loudil
+// *
+// */
+//public class JsonTransformer {
+//	private Logger logger = Logger.getLogger(JsonTransformer.class);
+//
+//	/**
+//	 *
+//	 * Deserialize input JSON and transform to graph JSON.
+//	 *
+//	 * @param inputJSON
+//	 * @param request
+//	 * @return
+//	 * @throws IOException
+//	 */
+//	public String transformInputJSONToGraphJSON(String inputJSON,
+//			HttpServletRequest request) throws IOException {
+//		CocaexWrapper efpResults;
+//
+//		GsonBuilder gsonBuilder = new GsonBuilder();
+//		// JSON deserializing adapter provided for EFP type classes
+//		gsonBuilder.registerTypeAdapter(EfpValueType.class,
+//				new EfpValueTypeAdapter());
+//		// JSON deserializing adapter for the Wrapper class
+//		gsonBuilder.registerTypeAdapter(CocaexWrapper.class,
+//				new WrapperDeserializer());
+//		Gson gson = gsonBuilder.create();
+//
+//		// decode + unzip received data
+//		String data = decompress(inputJSON);
+//
+//		// deserialize using deserializer adapters
+//		efpResults = gson.fromJson(data, CocaexWrapper.class);
+//
+//		request.setAttribute("efpPortalEfpNames", efpResults.getEfpMappings());
+//
+//		// transform received data to readable graph form
+//		EfpGraphTransfomer transformer = new EfpGraphTransfomer(efpResults);
+//		GraphInterface graph = transformer.transform();
+//		GraphExport export = new GraphExport(graph);
+//
+//		// transform graph to JSON
+//		JSONObject o = JSONObject.fromObject(export);
+//
+//		return o.toString();
+//	}
+//
+//	/**
+//	 * Decode and unzip a Base64 encoded GZIPed string.
+//	 *
+//	 * @param input
+//	 * @return
+//	 * @throws IOException
+//	 */
+//	private String decompress(String input) throws IOException {
+//		logger.trace("ENTRY");
+//		String result = null;
+//
+//		byte[] bytes = Base64.decodeBase64(input);
+//		GZIPInputStream zi = null;
+//		try {
+//			zi = new GZIPInputStream(new ByteArrayInputStream(bytes));
+//			result = IOUtils.toString(zi);
+//		} finally {
+//			IOUtils.closeQuietly(zi);
+//		}
+//		logger.trace("EXIT");
+//
+//		return result;
+//	}
+//
+//}
diff --git a/sources/src/cz/zcu/kiv/offscreen/efp/utils/WrapperDeserializer.java b/sources/src/cz/zcu/kiv/offscreen/efp/utils/WrapperDeserializer.java
index f9337de..fcff7f7 100644
--- a/sources/src/cz/zcu/kiv/offscreen/efp/utils/WrapperDeserializer.java
+++ b/sources/src/cz/zcu/kiv/offscreen/efp/utils/WrapperDeserializer.java
@@ -1,76 +1,76 @@
-package cz.zcu.kiv.offscreen.efp.utils;
-
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-import cz.zcu.kiv.efps.types.datatypes.EfpValueType;
-import cz.zcu.kiv.efps.types.serialisation.json.EfpValueTypeAdapter;
-import cz.zcu.kiv.offscreen.data.efpportal.CocaexData;
-import cz.zcu.kiv.offscreen.data.efpportal.CocaexWrapper;
-
-/**
- * 
- * CocaexWrapper class deserializer.
- * 
- * @author Jiri Loudil
- * 
- */
-public class WrapperDeserializer implements JsonDeserializer<CocaexWrapper> {
-	private Logger logger = Logger.getLogger(WrapperDeserializer.class);
-
-	@Override
-	public CocaexWrapper deserialize(JsonElement json, Type typeOfT,
-			JsonDeserializationContext context) {
-		logger.trace("ENTRY");
-
-		GsonBuilder gsonBuilder = new GsonBuilder();
-		// JSON deserializing adapter provided for EFP type classes
-		gsonBuilder.registerTypeAdapter(EfpValueType.class,
-				new EfpValueTypeAdapter());
-		Gson gson = gsonBuilder.create();
-
-		CocaexWrapper wrapper = gson.fromJson(json, CocaexWrapper.class);
-		JsonObject jo = json.getAsJsonObject();
-
-		Map<String, String> featureMappings = new HashMap<String, String>();
-		Map<String, String> efpMappings = new HashMap<String, String>();
-		Map<String, CocaexData> data = new HashMap<String, CocaexData>();
-
-		// parse feature mappings
-		JsonObject featuresObject = jo.getAsJsonObject("featureMappings");
-		for (Map.Entry<String, JsonElement> entry : featuresObject.entrySet()) {
-			featureMappings.put(entry.getKey(), entry.getValue().getAsString());
-		}
-
-		// parse efps mappings
-		JsonObject efpsObject = jo.getAsJsonObject("efpMappings");
-		for (Map.Entry<String, JsonElement> entry : efpsObject.entrySet()) {
-			efpMappings.put(entry.getKey(), entry.getValue().getAsString());
-		}
-
-		// parse data
-		JsonObject dataObject = jo.getAsJsonObject("data");
-		for (Map.Entry<String, JsonElement> entry : dataObject.entrySet()) {
-			data.put(entry.getKey(), (CocaexData) context.deserialize(
-					entry.getValue(), CocaexData.class));
-		}
-
-		// fill output structure
-		wrapper.setFeatureMappings(featureMappings);
-		wrapper.setEfpMappings(efpMappings);
-		wrapper.setData(data);
-		logger.trace("EXIT");
-
-		return wrapper;
-	}
-}
+//package cz.zcu.kiv.offscreen.efp.utils;
+//
+//import java.lang.reflect.Type;
+//import java.util.HashMap;
+//import java.util.Map;
+//
+//import org.apache.log4j.Logger;
+//
+//import com.google.gson.Gson;
+//import com.google.gson.GsonBuilder;
+//import com.google.gson.JsonDeserializationContext;
+//import com.google.gson.JsonDeserializer;
+//import com.google.gson.JsonElement;
+//import com.google.gson.JsonObject;
+//
+//import cz.zcu.kiv.efps.types.datatypes.EfpValueType;
+//import cz.zcu.kiv.efps.types.serialisation.json.EfpValueTypeAdapter;
+//import cz.zcu.kiv.offscreen.data.efpportal.CocaexData;
+//import cz.zcu.kiv.offscreen.data.efpportal.CocaexWrapper;
+//
+///**
+// *
+// * CocaexWrapper class deserializer.
+// *
+// * @author Jiri Loudil
+// *
+// */
+//public class WrapperDeserializer implements JsonDeserializer<CocaexWrapper> {
+//	private Logger logger = Logger.getLogger(WrapperDeserializer.class);
+//
+//	@Override
+//	public CocaexWrapper deserialize(JsonElement json, Type typeOfT,
+//			JsonDeserializationContext context) {
+//		logger.trace("ENTRY");
+//
+//		GsonBuilder gsonBuilder = new GsonBuilder();
+//		// JSON deserializing adapter provided for EFP type classes
+//		gsonBuilder.registerTypeAdapter(EfpValueType.class,
+//				new EfpValueTypeAdapter());
+//		Gson gson = gsonBuilder.create();
+//
+//		CocaexWrapper wrapper = gson.fromJson(json, CocaexWrapper.class);
+//		JsonObject jo = json.getAsJsonObject();
+//
+//		Map<String, String> featureMappings = new HashMap<String, String>();
+//		Map<String, String> efpMappings = new HashMap<String, String>();
+//		Map<String, CocaexData> data = new HashMap<String, CocaexData>();
+//
+//		// parse feature mappings
+//		JsonObject featuresObject = jo.getAsJsonObject("featureMappings");
+//		for (Map.Entry<String, JsonElement> entry : featuresObject.entrySet()) {
+//			featureMappings.put(entry.getKey(), entry.getValue().getAsString());
+//		}
+//
+//		// parse efps mappings
+//		JsonObject efpsObject = jo.getAsJsonObject("efpMappings");
+//		for (Map.Entry<String, JsonElement> entry : efpsObject.entrySet()) {
+//			efpMappings.put(entry.getKey(), entry.getValue().getAsString());
+//		}
+//
+//		// parse data
+//		JsonObject dataObject = jo.getAsJsonObject("data");
+//		for (Map.Entry<String, JsonElement> entry : dataObject.entrySet()) {
+//			data.put(entry.getKey(), (CocaexData) context.deserialize(
+//					entry.getValue(), CocaexData.class));
+//		}
+//
+//		// fill output structure
+//		wrapper.setFeatureMappings(featureMappings);
+//		wrapper.setEfpMappings(efpMappings);
+//		wrapper.setData(data);
+//		logger.trace("EXIT");
+//
+//		return wrapper;
+//	}
+//}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/Attribute.java b/sources/src/cz/zcu/kiv/offscreen/graph/Attribute.java
new file mode 100644
index 0000000..2a1ddd6
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/Attribute.java
@@ -0,0 +1,11 @@
+package cz.zcu.kiv.offscreen.graph;
+
+public class Attribute {
+    int typeIndex;
+    Object value;
+
+    public Attribute(int typeIndex, Object value) {
+        this.typeIndex = typeIndex;
+        this.value = value;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/EdgeArchetype.java b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeArchetype.java
new file mode 100644
index 0000000..28c8519
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeArchetype.java
@@ -0,0 +1,15 @@
+package cz.zcu.kiv.offscreen.graph;
+
+public class EdgeArchetype {
+    public String name;
+    public String text;
+
+    EdgeArchetype(String name, String text) {
+        this.name = name;
+        this.text = text;
+    }
+
+    public String getName() {
+        return  name;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/EdgeArchetypeInfo.java b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeArchetypeInfo.java
new file mode 100644
index 0000000..d61acfc
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeArchetypeInfo.java
@@ -0,0 +1,35 @@
+package cz.zcu.kiv.offscreen.graph;
+
+public class EdgeArchetypeInfo {
+    /**
+     * index of the archetype of the vertex the edge leads to
+     */
+    public int fromArchetypeIndex;
+
+    /**
+     * index of the archetype of the edge
+     */
+    public int edgeArchetypeIndex;
+
+    /**
+     * index of the archetype of the vertex the edge leads from
+     */
+    public int toArchetypeIndex;
+
+    public EdgeArchetypeInfo(int fromArchetypeIndex, int edgeArchetypeIndex, int toArchetypeIndex) {
+        this.fromArchetypeIndex = fromArchetypeIndex;
+        this.edgeArchetypeIndex = edgeArchetypeIndex;
+        this.toArchetypeIndex = toArchetypeIndex;
+    }
+
+    @Override
+    public int hashCode() {
+        return fromArchetypeIndex * 10000 + edgeArchetypeIndex * 100 + fromArchetypeIndex;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        EdgeArchetypeInfo info = (EdgeArchetypeInfo)obj;
+        return (info.fromArchetypeIndex == fromArchetypeIndex) && (info.edgeArchetypeIndex == edgeArchetypeIndex) && (info.toArchetypeIndex == toArchetypeIndex);
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/EdgeData.java b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeData.java
new file mode 100644
index 0000000..2e229d3
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeData.java
@@ -0,0 +1,54 @@
+package cz.zcu.kiv.offscreen.graph;
+
+import java.util.*;
+
+public class EdgeData {
+    public int id;
+    public int from;
+    public int to;
+    public String text;
+    public int archetypeIndex;
+    public Map<Integer, Attribute> attributes = new HashMap<>();
+
+    public EdgeData(int id, int from, int to, String text, int archetypeIndex) {
+        this.id = id;
+        this.from = from;
+        this.to = to;
+        this.text = text;
+        this.archetypeIndex = archetypeIndex;
+    }
+
+    public void addAttribute(int attrTypeIndex, Object value) {
+        Attribute attr = new Attribute(attrTypeIndex, value);
+        attributes.put(attrTypeIndex, attr);
+    }
+
+    public void addAttributes(Map<Integer, Attribute> attributes) {
+        this.attributes.putAll(attributes);
+    }
+
+    public Attribute getAttribute(int attrTypeIndex) {
+        return attributes.get(attrTypeIndex);
+    }
+
+    @Override
+    public int hashCode() {
+        return from * 100000 + to;
+    }
+
+    @Override
+    public boolean equals(Object edge) {
+        return from == ((EdgeData) edge).from && to == ((EdgeData) edge).to;
+    }
+
+    public List<Attribute> getSortedAttributes() {
+        List<Attribute> list = new ArrayList<>();
+        ArrayList<Integer> indices = new ArrayList<>(attributes.keySet());
+        //indices.sort(Integer::compareTo);
+        Collections.sort(indices); // TODO check correct order
+        for (int i = 0; i < indices.size(); i++) {
+            list.add(attributes.get(indices.get(i)));
+        }
+        return list;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/EdgeEfp.java b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeEfp.java
index fe0eab5..21b1de8 100644
--- a/sources/src/cz/zcu/kiv/offscreen/graph/EdgeEfp.java
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeEfp.java
@@ -1,6 +1,7 @@
 package cz.zcu.kiv.offscreen.graph;
 
 import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.log4j.Logger;
 
@@ -65,6 +66,16 @@ public class EdgeEfp implements EdgeInterface {
 		return edgeId;
 	}
 
+	@Override
+	public List<SubedgeInfo> getSubedgeInfo() {
+		return null;
+	}
+
+	@Override
+	public void setSubedgeInfo(List<SubedgeInfo> subedgeInfo) {
+		// TODO 30.7.2018 empty body (copy from CoCaEx ASWI)
+	}
+
 	public ArrayList<EfpFeature> getFeatures() {
 		return features;
 	}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/EdgeImpl.java b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeImpl.java
index ee6c16c..38cadec 100644
--- a/sources/src/cz/zcu/kiv/offscreen/graph/EdgeImpl.java
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/EdgeImpl.java
@@ -17,6 +17,7 @@ public class EdgeImpl implements EdgeInterface {
     private String to;
     private List<String> packageConnections;
     private boolean isCompatible;
+    private List<SubedgeInfo> subedgeInfo;
     private String compInfoJSON;
     private Logger logger = Logger.getLogger(EdgeImpl.class);
 
@@ -60,13 +61,30 @@ public class EdgeImpl implements EdgeInterface {
         return edgeId;
     }
 
+    @Override
+    public List<SubedgeInfo> getSubedgeInfo() {
+        return subedgeInfo;
+    }
+
+    @Override
+    public void setSubedgeInfo(List<SubedgeInfo> subedgeInfo) {
+        this.subedgeInfo = subedgeInfo;
+    }
+
+    @Override
+    public boolean equals(Object edge) {
+        if (!(edge instanceof EdgeImpl)) return false;
+        EdgeImpl cmpEdge = (EdgeImpl) edge;
+        return from.equals(cmpEdge.from) && to.equals(cmpEdge.to);
+    }
+
     public List<String> getPackageConnections() {
         logger.trace("ENTRY");
         logger.trace("EXIT");
         return this.packageConnections;
     }
 
-    public void setPackageConnection(List<String> packageConnections) {
+    public void setPackageConnections(List<String> packageConnections) {
         logger.trace("ENTRY");
         this.packageConnections = packageConnections;
         logger.trace("EXIT");
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/GraphExport.java b/sources/src/cz/zcu/kiv/offscreen/graph/GraphExport.java
index 78d9f40..74aed52 100644
--- a/sources/src/cz/zcu/kiv/offscreen/graph/GraphExport.java
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/GraphExport.java
@@ -1,10 +1,13 @@
 package cz.zcu.kiv.offscreen.graph;
 
+import cz.zcu.kiv.offscreen.AttributeType;
 import cz.zcu.kiv.offscreen.api.EdgeInterface;
 import cz.zcu.kiv.offscreen.api.GraphInterface;
 import cz.zcu.kiv.offscreen.api.VertexInterface;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+
 import org.apache.log4j.Logger;
 
 /*
@@ -19,12 +22,25 @@ public class GraphExport {
 
     private List<VertexInterface> vertices;
     private List<EdgeInterface> edges;
+    private List<VertexArchetype> vertexArchetypes;
+    private List<EdgeArchetype> edgeArchetypes;
+    private List<AttributeType> attributeTypes;
+    private Map<String, List<String>> possibleEnumValues;
+    private Map<String, String> archetypeIcons;
+    private List<Integer> defaultGroupArchetypes;
+
     private Logger logger = Logger.getLogger(GraphExport.class);
 
     public GraphExport(GraphInterface graph) {
         logger.trace("ENTRY");
         this.vertices = new ArrayList<VertexInterface>(graph.getVertices().values());
         this.edges = new ArrayList<EdgeInterface>(graph.getEdges());
+        this.vertexArchetypes = new ArrayList<VertexArchetype>(graph.getVertexArchetypes());
+        this.edgeArchetypes = new ArrayList<EdgeArchetype>(graph.getEdgeArchetypes());
+        this.attributeTypes = new ArrayList<>(graph.getAttributeTypes());
+        this.possibleEnumValues = graph.getPossibleEnumValues();
+        this.archetypeIcons = graph.getArchetypeIcons();
+        this.defaultGroupArchetypes = graph.getDefaultGroupArchetypes();
         logger.trace("EXIT");
     }
 
@@ -39,4 +55,28 @@ public class GraphExport {
         logger.trace("EXIT");
         return vertices;
     }
+
+    public List<VertexArchetype> getVertexArchetypes() {
+        return vertexArchetypes;
+    }
+
+    public List<EdgeArchetype> getEdgeArchetypes() {
+        return edgeArchetypes;
+    }
+
+    public List<AttributeType> getAttributeTypes() {
+        return attributeTypes;
+    }
+
+    public Map<String, List<String>> getPossibleEnumValues() {
+        return possibleEnumValues;
+    }
+
+    public Map<String, String> getArchetypeIcons() {
+        return archetypeIcons;
+    }
+
+    public List<Integer> getDefaultGroupArchetypes() {
+        return defaultGroupArchetypes;
+    }
 }
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/GraphImpl.java b/sources/src/cz/zcu/kiv/offscreen/graph/GraphImpl.java
index a11229e..af60c10 100644
--- a/sources/src/cz/zcu/kiv/offscreen/graph/GraphImpl.java
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/GraphImpl.java
@@ -1,5 +1,6 @@
 package cz.zcu.kiv.offscreen.graph;
 
+import cz.zcu.kiv.offscreen.AttributeType;
 import cz.zcu.kiv.offscreen.api.EdgeInterface;
 import cz.zcu.kiv.offscreen.api.GraphInterface;
 import cz.zcu.kiv.offscreen.api.VertexInterface;
@@ -18,6 +19,13 @@ public class GraphImpl implements GraphInterface {
     private Map<String, VertexInterface> vertices;
     private List<EdgeInterface> edges;
     private Logger logger = Logger.getLogger(GraphImpl.class);
+    private List<VertexArchetype> vertexArchetypes;
+    private List<EdgeArchetype> edgeArchetypes;
+    private List<AttributeType> attributeTypes;
+    private Map<String, List<String>> possibleEnumValues;
+    private List<Integer> defaultGroupArchetypes;
+
+    private Map<String, String> archetypeIcons;
 
     public GraphImpl() {
         logger.trace("ENTRY");
@@ -33,6 +41,68 @@ public class GraphImpl implements GraphInterface {
         return edges;
     }
 
+    @Override
+    public List<VertexArchetype> getVertexArchetypes() {
+        return vertexArchetypes;
+    }
+
+    @Override
+    public List<EdgeArchetype> getEdgeArchetypes() {
+        return edgeArchetypes;
+    }
+
+    @Override
+    public void setVertexArchetypes(List<VertexArchetype> vertexArchetypes) {
+        this.vertexArchetypes = vertexArchetypes;
+    }
+
+    @Override
+    public  void setEdgeArchetypes(List<EdgeArchetype> edgeArchetypes) {
+        this.edgeArchetypes = edgeArchetypes;
+    }
+
+    @Override
+    public void setAttributeTypes(List<AttributeType> attributeTypes) {
+        this.attributeTypes = attributeTypes;
+    }
+
+    @Override
+    public void setPossibleEnumValues(Map<Integer, List<String>> possibleEnumValues) {
+        this.possibleEnumValues = new HashMap<>();
+        for (Integer index : possibleEnumValues.keySet()) {
+            this.possibleEnumValues.put("" + index, possibleEnumValues.get(index));
+        }
+    }
+
+    public void setArchetypeIcons(Map<String, String> archetypeIcons) {
+        this.archetypeIcons = archetypeIcons;
+    }
+
+    @Override
+    public List<Integer> getDefaultGroupArchetypes() {
+        return defaultGroupArchetypes;
+    }
+
+    @Override
+    public void setDefaultGroupArchetypes(List<Integer> defaultGroupArchetypes) {
+        this.defaultGroupArchetypes = defaultGroupArchetypes;
+    }
+
+    @Override
+    public List<AttributeType> getAttributeTypes() {
+        return attributeTypes;
+    }
+
+    @Override
+    public Map<String, List<String>> getPossibleEnumValues() {
+        return possibleEnumValues;
+    }
+
+    @Override
+    public Map<String, String> getArchetypeIcons() {
+        return archetypeIcons;
+    }
+
     @Override
     public Map<String, VertexInterface> getVertices() {
         logger.trace("ENTRY");
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/GraphManager.java b/sources/src/cz/zcu/kiv/offscreen/graph/GraphManager.java
new file mode 100644
index 0000000..6a22bb5
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/GraphManager.java
@@ -0,0 +1,566 @@
+package cz.zcu.kiv.offscreen.graph;
+
+import cz.zcu.kiv.offscreen.AttributeType;
+import cz.zcu.kiv.offscreen.api.GraphInterface;
+import cz.zcu.kiv.offscreen.api.VertexInterface;
+import cz.zcu.kiv.offscreen.graph.filter.*;
+import cz.zcu.kiv.offscreen.graph.loader.JSONConfigLoader;
+
+import java.util.*;
+
+public class GraphManager {
+
+    public enum AttributeDataType {
+        NUMBER {
+            @Override
+            public String toString() {
+                return "number";
+            }
+        },
+        DATE {
+            @Override
+            public String toString() {
+                return "date";
+            }
+        },
+        ENUM {
+            @Override
+            public String toString() {
+                return "enum";
+            }
+        },
+        STRING {
+            @Override
+            public String toString() {
+                return "string";
+            }
+        }
+    }
+
+    public List<VertexArchetype> vertexArchetypes = new ArrayList<>();
+    public List<EdgeArchetype> edgeArchetypes = new ArrayList<>();
+    public List<AttributeType> attributeTypes = new ArrayList<>();
+
+    /**
+     * the key is the attributeType index, the value is the list of possible values
+     */
+    private Map<Integer, List<String>> possibleEnumValues = new HashMap<>();
+
+    /**
+     * key is the archetype index, value is the set of vertices of the given archetype
+     */
+    public Map<Integer, HashSet<VertexData>> vertices = new HashMap<>();
+
+    /**
+     * key is the triplet of archetypes {fromVertex, edge, toVertex}, value is the list of edges for the given archetype triplet
+     */
+    public Map<EdgeArchetypeInfo, List<EdgeData>> edges = new HashMap<>();
+
+    public void addVertexArchetype(String name, String text) {
+        vertexArchetypes.add(new VertexArchetype(name, text));
+    }
+
+    public void addEdgeArchetype(String name, String text) {
+        edgeArchetypes.add(new EdgeArchetype(name, text));
+    }
+
+    /**
+     *
+     * @param name
+     * @param dataType
+     * @param text
+     */
+    public void addAttributeType(String name, AttributeDataType dataType, String text) {
+        attributeTypes.add(new AttributeType(name, dataType, text));
+    }
+
+    /**
+     * Adds a list of values to the possible values hashmap. All duplicated are
+     * removed.
+     *
+     * @param attributeTypeId - Id of attribute type
+     * @param values          - List of values of the corresponding attribute type
+     */
+    public void addUniquePossibleAttributeValues(int attributeTypeId, List<String> values) {
+        if (possibleEnumValues.containsKey(attributeTypeId)) {
+            List<String> attrValues = possibleEnumValues.get(attributeTypeId);
+            List<String> valuesWithoutDuplicates = new ArrayList<>(new HashSet<>(values)); // Converting to hashset removes duplicates
+            valuesWithoutDuplicates.removeAll(attrValues);   // Values to add without values already present in the hashmap
+            attrValues.addAll(valuesWithoutDuplicates);
+        } else {
+            possibleEnumValues.put(attributeTypeId, values);
+        }
+    }
+
+    public List<Integer> getEnumPositionsForAttrIndex(int attributeTypeId, List<String> enumValues) {
+        List<Integer> positions = new ArrayList<>();
+        if (!possibleEnumValues.containsKey(attributeTypeId)) {
+            return positions;
+        }
+
+        List<String> possibleValues = possibleEnumValues.get(attributeTypeId);
+        for (int i = 0; i < possibleValues.size(); i++) {
+            String possibleValue = possibleValues.get(i);
+            if (enumValues.contains(possibleValue)) {
+                positions.add(i);
+            }
+        }
+
+        return positions;
+    }
+
+    /**
+     * Gets string values from possible enums for attribute type id.
+     * @param attributeTypeId - Id of the attribute type
+     * @param valuePositions - List of positions in the possible enums hashmap for which to find the enum values.
+     * @return - List of string values of enums.
+     */
+    private List<String> getEnumStringsForAttrIndex(int attributeTypeId, List<Integer> valuePositions) {
+        List<String> values = new ArrayList<>();
+
+        List<String> possibleValues = possibleEnumValues.get(attributeTypeId);
+        for (int i = 0; i < possibleValues.size(); i++) {
+            if (valuePositions.contains(i)) {
+                values.add(possibleValues.get(i));
+            }
+        }
+
+        return values;
+    }
+
+    public AttributeType getAttributeDataTypeByName(String attributeName) {
+        return attributeTypes.get(getAttributeIndex(attributeName));
+    }
+
+    /**
+     * Adds a record to the possibleEnumValues hashset of the attributes possible values.
+     *
+     * @param attributeIndex - Index of the attribute for which to add the possible values
+     * @param possibleValues - All the possible values of the attribute
+     */
+    public void addEnumValues(int attributeIndex, List<String> possibleValues) {
+        possibleEnumValues.put(attributeIndex, possibleValues);
+    }
+
+    /**
+     * Creates a new vertex from input parameters and adds it to the map of
+     * vertices with the archetypeIndex as the key.
+     *
+     * @param id             - ID of the vertex to add
+     * @param title          - Title of the vertex
+     * @param text           - Text of the vertex
+     * @param archetypeIndex - Type of archetype associated with this vertex
+     * @param attributes     - Map of attributes associated with the vertex
+     */
+    public void addVertex(int id, String title, String text, int archetypeIndex, Map<Integer, Attribute> attributes) {
+        VertexData vertexToAdd = new VertexData(id, title, text, archetypeIndex);
+        if (vertices.containsKey(archetypeIndex)) {
+            vertices.get(archetypeIndex).add(vertexToAdd);
+        } else {
+            HashSet<VertexData> vertexSet = new HashSet<>();
+            vertexSet.add(vertexToAdd);
+            vertices.put(archetypeIndex, vertexSet);
+        }
+
+        vertexToAdd.addAttributes(attributes);
+    }
+
+    /**
+     * Creates a new edge from input parameters and adds it to the map of
+     * edges with the archetypeIndex as the key.
+     *
+     * @param id            - ID of the edge to add
+     * @param from          - ID of the vertex the edge comes from
+     * @param to            - ID of the vertex the edge points to
+     * @param text          - Text of edge
+     * @param archetypeInfo - The archetype information associated with this edge
+     * @param attributes    - Map of attributes associated with the edge
+     */
+    public void addEdge(int id, int from, int to, String text, EdgeArchetypeInfo archetypeInfo, Map<Integer, Attribute> attributes) {
+        EdgeData edgeToAdd = new EdgeData(id, from, to, text, archetypeInfo.edgeArchetypeIndex);
+        if (edges.containsKey(archetypeInfo)) {
+            edges.get(archetypeInfo).add(edgeToAdd);
+        } else {
+            List<EdgeData> edgesList = new ArrayList<>();
+            edgesList.add(edgeToAdd);
+            edges.put(archetypeInfo, edgesList);
+        }
+
+        edgeToAdd.addAttributes(attributes);
+    }
+
+    /**
+     * returns the index of a given enum value in the list of the possible enum values
+     * @param value the enum value
+     * @return index in the list of possible enum values or -1 if the value is not in the list
+     */
+    public int getEnumValueIndex(int attributeTypeIndex, String value) {
+        int index = -1;
+        List<String> values = possibleEnumValues.get(attributeTypeIndex);
+        for (int i = 0; i < values.size(); i++) {
+            if (values.get(i).equals(value)) {
+                index = i;
+                break;
+            }
+        }
+        return index;
+    }
+
+    /**
+     * returns the index of an attribute with a given name in the attributeTypes list
+     * @param name the name of the attribute
+     * @return the attribute index or -1 if there is no attribute with such a name
+     */
+    public int getAttributeIndex(String name) {
+        int index = -1;
+        for (int i = 0; i < attributeTypes.size(); i++) {
+            if (attributeTypes.get(i).name.equals(name)) {
+                index = i;
+                break;
+            }
+        }
+        return index;
+    }
+
+    /**
+     * returns the index of an archetype with a given name in the vertexArchetypes list
+     * @param archetypeName name of the archetype
+     * @return the index or -1 if there is no archetype with the given name in the list
+     */
+    public int getVertexArchetypeIndex(String archetypeName) {
+        int index = -1;
+        for (int i = 0; i < vertexArchetypes.size(); i++) {
+            if (vertexArchetypes.get(i).name.equals(archetypeName)) {
+                index = i;
+                break;
+            }
+        }
+        return index;
+    }
+
+    /**
+     * returns the index of an archetype with a given name in the edgeArchetypes list
+     * @param archetypeName name of the archetype
+     * @return the index or -1 if there is no archetype with the given name in the list
+     */
+    public int getEdgeArchetypeIndex(String archetypeName) {
+        int index = -1;
+        for (int i = 0; i < edgeArchetypes.size(); i++) {
+            if (edgeArchetypes.get(i).name.equals(archetypeName)) {
+                index = i;
+                break;
+            }
+        }
+        return index;
+    }
+
+    /**
+     * Filters the edges and vertices according to the default filter loaded from the configuration file
+     * and constructs the {@code GraphImpl} object.
+     * @param configLoader - The object that loads the configuration file.
+     * @return - Constructed {@code GraphImpl} object.
+     */
+    public GraphInterface createGraph(JSONConfigLoader configLoader) {
+        GraphInterface graph = new GraphImpl();
+
+        // To use default filter from a configuration file
+        GraphFilter filter = configLoader.loadDefaultFilter();
+        if (filter == null) {
+            // To Enable Everything
+            filter = new GraphFilter();
+            filter.setVertexArchetypeFilter(new ArrayList<Integer>(), GraphFilter.ArchetypeMatchType.NON_MATCHING);
+            filter.setEdgeArchetypeFilter(new ArrayList<EdgeArchetypeInfo>(), GraphFilter.ArchetypeMatchType.NON_MATCHING);
+        }
+
+        Map<String, String> archetypeIcons = configLoader.loadArchetypeIcons();
+        graph.setArchetypeIcons(archetypeIcons);
+
+        List<Integer> defaultGroupArchetypes = configLoader.loadGroupArchetypes();
+        graph.setDefaultGroupArchetypes(defaultGroupArchetypes);
+
+        Set<VertexData> resultVertices = getVerticesByArchetypeFilter(filter);
+
+        resultVertices = getVerticesByAttributeFilter(filter, resultVertices);
+
+        List<EdgeData> resultEdges = getEdgesByArchetypeFilter(filter, resultVertices);
+
+        resultEdges = getEdgesByAttributeFilter(filter, resultEdges);
+
+        addVerticesToGraph(graph, resultVertices);
+
+        addEdgesToGraph(graph, resultEdges);
+
+        graph.setAttributeTypes(attributeTypes);
+        graph.setPossibleEnumValues(possibleEnumValues);
+
+        return graph;
+    }
+
+    /**
+     * Gets filtered vertices by attributes.
+     * @param filter - Filter object.
+     * @param vertices - List of vertices for filtration.
+     * @return - List of vertices filtered by attribute.
+     */
+    private Set<VertexData> getVerticesByAttributeFilter(GraphFilter filter, Set<VertexData> vertices) {
+        Set<VertexData> resultVertices = new HashSet<>();
+        for (VertexData vertex : vertices) {
+            boolean filterPassed = true;
+            AttributeFilter attributeFilter = filter.getVertexAttributeFilter(vertex.archetypeIndex);
+            if (attributeFilter != null) {
+                // Iterate through all attributes of the vertex
+                for (int attributeIndex : vertex.attributes.keySet()) {
+                    Attribute vertexAttribute = vertex.attributes.get(attributeIndex);
+
+                    filterPassed = (filterPassed && checkAttributeFiltersPassed(vertexAttribute, attributeFilter, attributeIndex));
+                    if (!filterPassed) break;   // filter did not pass
+                }
+            }
+            if (filterPassed)
+                resultVertices.add(vertex);
+        }
+        return resultVertices;
+    }
+
+    /**
+     * Gets filtered edges by attribute.
+     * @param filter - Filter object.
+     * @param edges - List of edges for filtration.
+     * @return - List of edges filtered by attribute.
+     */
+    private List<EdgeData> getEdgesByAttributeFilter(GraphFilter filter, List<EdgeData> edges) {
+        List<EdgeData> resultEdges = new ArrayList<>();
+        for (EdgeData edge : edges) {
+            boolean filterPassed = true;
+            AttributeFilter attributeFilter = filter.getEdgeAttributeFilter(edge.archetypeIndex);
+            if (attributeFilter != null) {
+                // Iterate through all attributes of the edge
+                for (int attributeIndex : edge.attributes.keySet()) {
+                    Attribute edgeAttribute = edge.attributes.get(attributeIndex);
+
+                    filterPassed = (filterPassed && checkAttributeFiltersPassed(edgeAttribute, attributeFilter, attributeIndex));
+                    if (!filterPassed) break;   // filter did not pass
+                }
+            }
+            if (filterPassed)
+                resultEdges.add(edge);
+        }
+
+        return resultEdges;
+    }
+
+    /**
+     * Filters the attribute by its attribute filters and checks if it passed.
+     * @param vertexAttribute - Attribute object to filter.
+     * @param attributeFilter - Attribute filter of the attribute.
+     * @param attributeIndex - Index of the attribute.
+     * @return - true if passed the filter, else false.
+     */
+    private boolean checkAttributeFiltersPassed(Attribute vertexAttribute, AttributeFilter attributeFilter, int attributeIndex) {
+        AttributeDataType attributeType = attributeTypes.get(vertexAttribute.typeIndex).dataType;
+
+        boolean filterPassed;
+        ITypeAttributeFilter typeFilter = null;
+        switch (attributeType) {
+            case NUMBER:
+                typeFilter = attributeFilter.getNumberFilter(attributeIndex);
+                break;
+            case DATE:
+                typeFilter = attributeFilter.getDateFilter(attributeIndex);
+                break;
+            case ENUM:
+                typeFilter = attributeFilter.getEnumFilter(attributeIndex);
+                break;
+            case STRING:
+                typeFilter = attributeFilter.getStringFilter(attributeIndex);
+                break;
+        }
+        if (typeFilter == null) { // No filters mean pass
+            return true;
+        }
+
+        filterPassed = typeFilter.filter(vertexAttribute.value);
+
+        return filterPassed;
+    }
+
+    /**
+     * Filters vertices by archetype from the specified filter object.
+     *
+     * @param filter - Filter to be applied to the vertices.
+     * @return A list of vertices filtered by the specified filter object.
+     */
+    private HashSet<VertexData> getVerticesByArchetypeFilter(GraphFilter filter) {
+        HashSet<VertexData> resultVertices = new HashSet<>();
+
+        VertexArchetypeFilter vertexArchetypeFilter = filter.getVertexArchetypeFilter();
+        List<Integer> archetypesFiltered = vertexArchetypeFilter.archetypeIndeces;
+        switch (vertexArchetypeFilter.matchType) {
+            case MATCHING:
+                for (Integer vertexArchetypeIndex : vertices.keySet()){
+                    if (archetypesFiltered.contains(vertexArchetypeIndex)) {
+                        resultVertices.addAll(vertices.get(vertexArchetypeIndex));
+                    }
+                }
+                break;
+            case NON_MATCHING:
+                for (Integer vertexArchetypeIndex : vertices.keySet()){
+                    if (!archetypesFiltered.contains(vertexArchetypeIndex)) {
+                        resultVertices.addAll(vertices.get(vertexArchetypeIndex));
+                    }
+                }
+                break;
+        }
+
+        return resultVertices;
+    }
+
+    /**
+     * Filters edges by archetype from the specified filter object. Also removes all edges that contain either a vertex
+     * from which the edge originates or to which the edge leads.
+     *
+     * @param filter         - Filter to be applied to the edges list.
+     * @param resultVertices - List of vertices which should be present in the result graph.
+     * @return A list of edges filtered by the specified filter object
+     */
+    private List<EdgeData> getEdgesByArchetypeFilter(GraphFilter filter, Set<VertexData> resultVertices) {
+        List<EdgeData> resultEdges = new ArrayList<>();
+
+        EdgeArchetypeFilter edgeArchetypeFilter = filter.getEdgeArchetypeFilter();
+        List<EdgeArchetypeInfo> edgeInfosFiltered = edgeArchetypeFilter.archetypeIndeces;
+        switch (edgeArchetypeFilter.matchType) {
+            case MATCHING:
+                for (EdgeArchetypeInfo edgeInfo : edges.keySet()){
+                    if (edgeInfosFiltered.contains(edgeInfo)) {
+                        resultEdges.addAll(edges.get(edgeInfo));
+                    }
+                }
+                break;
+            case NON_MATCHING:
+                for (EdgeArchetypeInfo edgeInfo : edges.keySet()){
+                    if (!edgeInfosFiltered.contains(edgeInfo)) {
+                        resultEdges.addAll(edges.get(edgeInfo));
+                    }
+                }
+                break;
+        }
+
+        Iterator<EdgeData> i = resultEdges.iterator();
+        while (i.hasNext()) {
+            EdgeData edge = i.next();
+
+            VertexData toDummy = new VertexData(edge.to, null, null, -1);
+            VertexData fromDummy = new VertexData(edge.from, null, null, -1);
+
+            if (!resultVertices.contains(toDummy) || !resultVertices.contains(fromDummy)){
+                i.remove();
+            }
+        }
+
+        return resultEdges;
+    }
+
+    /**
+     * Adds edges to graph.
+     * @param graph - graph to which add the edges
+     * @param resultEdges - List of edges to add to the graph.
+     */
+    private void addEdgesToGraph(GraphInterface graph, List<EdgeData> resultEdges) {
+        HashMap<EdgeData, List<SubedgeInfo>> edgeSet = new HashMap<>();
+
+        for (EdgeData edgeData : resultEdges) {
+            ArrayList<String[]> attributes = new ArrayList<>();
+            for (Attribute attr : edgeData.getSortedAttributes()) {
+                String attrName = attributeTypes.get(attr.typeIndex).name;
+                AttributeDataType attrType = attributeTypes.get(attr.typeIndex).dataType;
+
+                StringBuilder attrValue = getAttributeValue(attr, attrType);
+                attributes.add(new String[]{attrName, attrValue.toString()});
+            }
+
+            SubedgeInfo subedgeInfo = new SubedgeInfo(edgeData.archetypeIndex, attributes);
+            subedgeInfo.id = edgeData.id;
+            if (edgeSet.containsKey(edgeData)) {
+                edgeSet.get(edgeData).add(subedgeInfo);
+            } else {
+                List<SubedgeInfo> subEdgeInfoList = new ArrayList<>();
+                subEdgeInfoList.add(subedgeInfo);
+                edgeSet.put(new EdgeData(edgeData.id, edgeData.from, edgeData.to, edgeData.text, edgeData.archetypeIndex), subEdgeInfoList);
+            }
+        }
+
+        int idCounter = 1;
+        for (EdgeData edgeData : edgeSet.keySet()) {
+            EdgeImpl edge = new EdgeImpl(idCounter++, "" + edgeData.from, "" + edgeData.to, true, "[]");
+            edge.setSubedgeInfo(edgeSet.get(edgeData));
+            graph.addEdge(edge);
+        }
+        graph.setVertexArchetypes(vertexArchetypes);
+        graph.setEdgeArchetypes(edgeArchetypes);
+    }
+
+    /**
+     * Adds vertices to the graph.
+     * @param graph - Graph to which add the vertices.
+     * @param resultVertices - List of vertices to add to the graph.
+     */
+    private void addVerticesToGraph(GraphInterface graph, Set<VertexData> resultVertices) {
+        int idCounter = 1;
+        for (VertexData vertexData : resultVertices) {
+            VertexArchetype archetype = vertexArchetypes.get(vertexData.archetypeIndex);
+            VertexInterface vertex = new VertexImpl(idCounter++, archetype.name + ":" + vertexData.title, "" + vertexData.id);
+
+            ArrayList<String> attributeStrings = new ArrayList<>();
+            ArrayList<String[]> attributes = new ArrayList<>();
+            for (Attribute attr : vertexData.getSortedAttributes()) {
+                String attrName = attributeTypes.get(attr.typeIndex).name;
+                AttributeDataType attrType = attributeTypes.get(attr.typeIndex).dataType;
+
+                StringBuilder attrValue;
+
+                attrValue = getAttributeValue(attr, attrType);
+
+                attributeStrings.add(attrName + ": " + attrValue);
+                attributes.add(new String[]{attrName, attrValue.toString()});
+            }
+
+            vertex.setExportedPackages(attributeStrings);
+            vertex.setArchetype(vertexData.archetypeIndex);
+            vertex.setAttributes(attributes);
+            graph.addVertex("" + vertexData.id, vertex);
+        }
+    }
+
+    /**
+     * Gets the string value of attribute by its data type.
+     * @param attr - Attribute object from which to extract the value.
+     * @param attrType - Data type of the attribute.
+     * @return - String value of the attribute.
+     */
+    private StringBuilder getAttributeValue(Attribute attr, AttributeDataType attrType) {
+        StringBuilder attrValue;
+        switch (attrType) {
+            case NUMBER:
+                attrValue = new StringBuilder(attr.value.toString());
+                break;
+            case DATE:
+                attrValue = new StringBuilder(attr.value.toString());
+                break;
+            case ENUM: // Enum attribute type must be a list of integers!
+                List<Integer> valuePositions = (List<Integer>) attr.value;
+                List<String> values = getEnumStringsForAttrIndex(attr.typeIndex, valuePositions);
+
+                attrValue = new StringBuilder();
+                for (int j = 0; j < values.size(); j++) {
+                    attrValue.append(values.get(j));
+                    if (j < values.size() - 1)
+                        attrValue.append(", ");
+                }
+                break;
+            default:
+                attrValue = new StringBuilder(attr.value.toString());
+                break;
+        }
+        return attrValue;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/SubedgeInfo.java b/sources/src/cz/zcu/kiv/offscreen/graph/SubedgeInfo.java
new file mode 100644
index 0000000..a0d0f5d
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/SubedgeInfo.java
@@ -0,0 +1,30 @@
+package cz.zcu.kiv.offscreen.graph;
+
+import java.util.List;
+
+public class SubedgeInfo {
+    private int archetype;
+
+    /**
+     * the original id of the edge in the input file, does not need to be set, but can be used for testing
+     */
+    public int id;
+
+    /**
+     * list of attributes, the first value in each array is the attribute's name and the second value is its value
+     */
+    private List<String[]> attributes;
+
+    public SubedgeInfo(int archetype, List<String[]> attributes) {
+        this.archetype = archetype;
+        this.attributes = attributes;
+    }
+
+    public int getArchetype() {
+        return archetype;
+    }
+
+    public List<String[]> getAttributes() {
+        return attributes;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/VertexArchetype.java b/sources/src/cz/zcu/kiv/offscreen/graph/VertexArchetype.java
new file mode 100644
index 0000000..d64c50a
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/VertexArchetype.java
@@ -0,0 +1,15 @@
+package cz.zcu.kiv.offscreen.graph;
+
+public class VertexArchetype {
+    public String name;
+    public String text;
+
+    VertexArchetype(String name, String text) {
+        this.name = name;
+        this.text = text;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/VertexData.java b/sources/src/cz/zcu/kiv/offscreen/graph/VertexData.java
new file mode 100644
index 0000000..d03fee5
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/VertexData.java
@@ -0,0 +1,53 @@
+package cz.zcu.kiv.offscreen.graph;
+
+import java.util.*;
+
+public class VertexData {
+    public int id;
+    public String title;
+    public String text;
+    public int archetypeIndex;
+    public Map<Integer, Attribute> attributes = new HashMap<>();
+
+    public VertexData(int id, String title, String text, int archetypeIndex) {
+        this.id = id;
+        this.title = title;
+        this.text = text;
+        this.archetypeIndex = archetypeIndex;
+    }
+
+    public void addAttribute(int attrTypeIndex, Object value) {
+        Attribute attr = new Attribute(attrTypeIndex, value);
+        attributes.put(attrTypeIndex, attr);
+    }
+
+    public Attribute getAttribute(int attrTypeIndex) {
+        return attributes.get(attrTypeIndex);
+    }
+
+    @Override
+    public int hashCode() {
+        return id;
+    }
+
+    @Override
+    public boolean equals(Object edge) {
+        if (!(edge instanceof VertexData)) return false;
+        return id == ((VertexData) edge).id;
+    }
+
+    public void addAttributes(Map<Integer, Attribute> attributes) {
+        this.attributes.putAll(attributes);
+    }
+
+    public List<Attribute> getSortedAttributes() {
+        List<Attribute> list = new ArrayList<>();
+        ArrayList<Integer> indices = new ArrayList<>(attributes.keySet());
+        //indices.sort(Integer::compareTo);
+        Collections.sort(indices); // TODO check correct order
+        for (int i = 0; i < indices.size(); i++) {
+            list.add(attributes.get(indices.get(i)));
+        }
+        return list;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/VertexEfp.java b/sources/src/cz/zcu/kiv/offscreen/graph/VertexEfp.java
index a4b6c38..f17f0d5 100644
--- a/sources/src/cz/zcu/kiv/offscreen/graph/VertexEfp.java
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/VertexEfp.java
@@ -8,9 +8,9 @@ import org.apache.log4j.Logger;
 import cz.zcu.kiv.offscreen.api.VertexInterface;
 
 /**
- * 
+ *
  * @author Jiri Loudil
- * 
+ *
  */
 public class VertexEfp implements VertexInterface {
 	private int id;
@@ -23,7 +23,7 @@ public class VertexEfp implements VertexInterface {
 	private Logger logger = Logger.getLogger(VertexEfp.class);
 
 	/**
-	 * 
+	 *
 	 * @param id
 	 * @param name
 	 * @param symbolicName
@@ -33,9 +33,9 @@ public class VertexEfp implements VertexInterface {
 		this.id = id;
 		this.name = name;
 		this.symbolicName = symbolicName;
-		
+
 		this.exportedPackages = new LinkedList<String>();
-        this.importedPackages = new LinkedList<String>();
+		this.importedPackages = new LinkedList<String>();
 
 		logger.trace("EXIT");
 	}
@@ -89,4 +89,24 @@ public class VertexEfp implements VertexInterface {
 		logger.trace("EXIT");
 	}
 
+	@Override
+	public int getArchetype() {
+		return 0;
+	}
+
+	@Override
+	public void setArchetype(int archetype) {
+
+	}
+
+	@Override
+	public void setAttributes(List<String[]> attributes) {
+
+	}
+
+	@Override
+	public List<String[]> getAttributes() {
+		return null;
+	}
+
 }
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/VertexImpl.java b/sources/src/cz/zcu/kiv/offscreen/graph/VertexImpl.java
index a83257a..72b8750 100644
--- a/sources/src/cz/zcu/kiv/offscreen/graph/VertexImpl.java
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/VertexImpl.java
@@ -3,6 +3,7 @@ package cz.zcu.kiv.offscreen.graph;
 import cz.zcu.kiv.offscreen.api.VertexInterface;
 import java.util.LinkedList;
 import java.util.List;
+
 import org.apache.log4j.Logger;
 
 /**
@@ -16,7 +17,12 @@ public class VertexImpl implements VertexInterface {
     private String symbolicName;
     private List<String> exportedPackages;
     private List<String> importedPackages;
+    private int archetype;
     private Logger logger = Logger.getLogger(VertexImpl.class);
+    /**
+     * list of attributes, the first value in each array is the attribute's name and the second value is its value
+     */
+    private List<String[]> attributes;
 //    private List<EdgeInterface> edges;
 
     public VertexImpl(int id, String name, String symbolicName) {
@@ -30,7 +36,7 @@ public class VertexImpl implements VertexInterface {
 //        this.edges = new ArrayList<EdgeInterface>();
     }
 
-//    public List<EdgeInterface> getEdges() {
+    //    public List<EdgeInterface> getEdges() {
 //        return edges;
 //    }
     @Override
@@ -49,21 +55,21 @@ public class VertexImpl implements VertexInterface {
 //    public void addEdge(EdgeInterface edge){
 //        this.edges.add(edge);
 //    }
-    
+
     @Override
     public List<String> getExportedPackages() {
         logger.trace("ENTRY");
         logger.trace("EXIT");
         return this.exportedPackages;
     }
-    
+
     @Override
     public List<String> getImportedPackages() {
         logger.trace("ENTRY");
         logger.trace("EXIT");
         return this.importedPackages;
     }
-    
+
     @Override
     public void setExportedPackages(List<String> exportedPackages) {
         logger.trace("ENTRY");
@@ -78,6 +84,26 @@ public class VertexImpl implements VertexInterface {
         logger.trace("EXIT");
     }
 
+    @Override
+    public int getArchetype() {
+        return archetype;
+    }
+
+    @Override
+    public void setArchetype(int archetype) {
+        this.archetype = archetype;
+    }
+
+    @Override
+    public void setAttributes(List<String[]> attributes) {
+        this.attributes = attributes;
+    }
+
+    @Override
+    public List<String[]> getAttributes() {
+        return attributes;
+    }
+
     @Override
     public String getSymbolicName() {
         return this.symbolicName;
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/creator/EfpGraphTransfomer.java b/sources/src/cz/zcu/kiv/offscreen/graph/creator/EfpGraphTransfomer.java
index 62f06a2..fb8f0eb 100644
--- a/sources/src/cz/zcu/kiv/offscreen/graph/creator/EfpGraphTransfomer.java
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/creator/EfpGraphTransfomer.java
@@ -1,397 +1,397 @@
-package cz.zcu.kiv.offscreen.graph.creator;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-
-import cz.zcu.kiv.efps.comparator.result.EfpEvalResult.MatchingResult;
-import cz.zcu.kiv.offscreen.api.EdgeInterface;
-import cz.zcu.kiv.offscreen.api.GraphInterface;
-import cz.zcu.kiv.offscreen.api.VertexInterface;
-import cz.zcu.kiv.offscreen.data.efpportal.CocaexData;
-import cz.zcu.kiv.offscreen.data.efpportal.CocaexDataEfp;
-import cz.zcu.kiv.offscreen.data.efpportal.CocaexDataFeature;
-import cz.zcu.kiv.offscreen.data.efpportal.CocaexWrapper;
-import cz.zcu.kiv.offscreen.graph.EdgeEfp;
-import cz.zcu.kiv.offscreen.graph.GraphImpl;
-import cz.zcu.kiv.offscreen.graph.VertexEfp;
-import cz.zcu.kiv.offscreen.graph.efp.EfpComparison;
-import cz.zcu.kiv.offscreen.graph.efp.EfpFeature;
-
-/**
- * 
- * Transforms data obtained in form of Map<String, CocaexData> to
- * cz.zcu.kiv.offscreen.api.GraphInterface.
- * 
- * @author Jiri Loudil
- * 
- */
-public class EfpGraphTransfomer {
-	
-	private final String DELIMITER = ";";
-
-	/**
-	 * Output data format.
-	 */
-	private GraphInterface graph = null;
-
-	/**
-	 * Input data format.
-	 */
-	private Map<String, CocaexData> resultData = null;
-
-	private Map<String, String> resultFeaturesMapping = null;
-
-	private Map<String, String> resultEfpsMapping = null;
-
-	/**
-	 * Already used vertices.
-	 */
-	private Map<String, VertexInterface> vertexMap;
-
-	/**
-	 * Already used features.
-	 */
-	private Map<String, EfpFeature> featureMap;
-
-	/**
-	 * Logging.
-	 */
-	private Logger logger = Logger.getLogger(EfpGraphTransfomer.class);
-
-	/**
-	 * New transformer from input data.
-	 * 
-	 * @param efpportalResultsWrapper
-	 *            Input data in from of EfpPortal app.
-	 */
-	public EfpGraphTransfomer(CocaexWrapper efpportalResultsWrapper) {
-		logger.trace("ENTRY");
-		this.graph = new GraphImpl();
-
-		this.resultData = efpportalResultsWrapper.getData();
-		this.resultEfpsMapping = efpportalResultsWrapper.getEfpMappings();
-		this.resultFeaturesMapping = efpportalResultsWrapper
-				.getFeatureMappings();
-
-		this.vertexMap = new HashMap<String, VertexInterface>();
-		this.featureMap = new HashMap<String, EfpFeature>();
-
-		logger.trace("EXIT");
-	}
-
-	/**
-	 * Generates the graph with vertices and edges.
-	 * 
-	 * @return graph
-	 */
-	public GraphInterface transform() {
-		logger.trace("ENTRY");
-		this.generateVertices();
-		this.generateEdges();
-
-		// set proper feature and efp names
-		this.setNamesInsteadOfNumbers();
-		logger.trace("EXIT");
-
-		return this.graph;
-	}
-
-	/**
-	 * Substitute ID for the proper name string.
-	 */
-	private void setNamesInsteadOfNumbers() {
-		logger.trace("ENTRY");
-
-		List<EdgeInterface> edges = graph.getEdges();
-
-		for (EdgeInterface edgeInterface : edges) {
-			ArrayList<EfpFeature> features = ((EdgeEfp) edgeInterface)
-					.getFeatures();
-
-			for (EfpFeature efpFeature : features) {
-				// substitute ID for the true name from the feature mapping
-				String tmpFeatureName = resultFeaturesMapping.get(efpFeature.getName());
-
-				efpFeature.setName(tmpFeatureName.split(DELIMITER)[1]);
-
-				ArrayList<EfpComparison> efps = efpFeature.getEfps();
-
-				for (EfpComparison efpComparison : efps) {
-					// substitute ID for the true name from the efps mapping
-					efpComparison.setEfpName(resultEfpsMapping
-							.get(efpComparison.getEfpName()));
-				}
-			}
-		}
-
-		logger.trace("EXIT");
-	}
-
-	/**
-	 * Generate vertices for this graph.
-	 */
-	private void generateVertices() {
-		logger.trace("ENTRY");
-
-		int id = 0;
-		VertexEfp vertex;
-
-		for (Map.Entry<String, CocaexData> tmpData : resultData.entrySet()) {
-			id++;
-
-			vertex = new VertexEfp(id, tmpData.getKey(), tmpData.getKey());
-
-			this.graph.addVertex(tmpData.getKey(), vertex);
-			this.vertexMap.put(tmpData.getKey(), vertex);
-		}
-
-		logger.trace("EXIT");
-	}
-
-	/**
-	 * Generate edges for this graph.
-	 */
-	private void generateEdges() {
-		logger.trace("ENTRY");
-
-		int id = 0;
-		String from, to;
-		CocaexData currentEvaluatedVertexData;
-
-		for (Map.Entry<String, VertexInterface> currentVertex : vertexMap
-				.entrySet()) {
-			currentEvaluatedVertexData = resultData.get(currentVertex.getKey());
-
-			to = currentVertex.getKey();
-
-			// all required features FROM
-			for (Map.Entry<String, CocaexDataFeature> tmpRequired : currentEvaluatedVertexData
-					.getRequiredFeatures().entrySet()) {
-
-				String requiredFeatureName = this.resultFeaturesMapping
-						.get(tmpRequired.getKey());
-
-				// get feature name, its first part is component name
-				String[] requiredSplits = requiredFeatureName.split(DELIMITER);
-
-				// not-connected ones are left over
-				if (!requiredSplits[0].isEmpty()) {
-
-					// vertex from == vertex to -> we dont want that...
-					if (requiredSplits[0].equals(currentVertex.getKey())) {
-						continue;
-					}
-
-					// find corresponding feature on the TO vertex
-					CocaexData otherVertexData = resultData
-							.get(requiredSplits[0]);
-					CocaexDataFeature otherVertexFeature = null;
-
-					// go through all features of the TO  
-					for (Map.Entry<String, CocaexDataFeature> tmpProvided : otherVertexData
-							.getProvidedFeatures().entrySet()) {
-						String providedFeatureName = this.resultFeaturesMapping
-								.get(tmpProvided.getKey());
-
-						String[] providedSplits = providedFeatureName
-								.split(DELIMITER);
-
-						// not-connected ones are left over
-						if (providedSplits[0].isEmpty()) {
-							continue;
-						}
-
-						// found matching feature between TO and FROM
-						if (providedSplits[0].equals(currentVertex.getKey())
-								&& providedSplits[1].equals(requiredSplits[1])) {
-							otherVertexFeature = tmpProvided.getValue();
-						}
-					}
-
-					from = requiredSplits[0];
-
-					EdgeEfp edge = findEdgeInGraph(from, to);
-
-					// add new edge
-					if (edge == null) {
-						edge = new EdgeEfp(++id, from, to);
-						// from to
-						checkAddEdgeFeature(tmpRequired.getValue(),
-								otherVertexFeature, tmpRequired.getKey(), edge);
-
-						this.graph.addEdge(edge);
-					} else {
-						// add a feature to an old edge only
-						checkAddEdgeFeature(tmpRequired.getValue(),
-								otherVertexFeature, tmpRequired.getKey(), edge);
-					}
-				}
-
-			}
-		}
-
-		logger.trace("EXIT");
-	}
-
-	/**
-	 * 
-	 * Find an existing edge in graph.
-	 * 
-	 * @param from
-	 *            Name of start vertex.
-	 * @param to
-	 *            name of end vertex.
-	 * @return Null if not found, edge otherwise.
-	 */
-	private EdgeEfp findEdgeInGraph(String from, String to) {
-		logger.trace("ENTRY");
-		List<EdgeInterface> tmpEdges = this.graph.getEdges();
-
-		for (EdgeInterface edge : tmpEdges) {
-			// found old edge
-			if (edge.getFrom().equals(from) && edge.getTo().equals(to)) {
-				logger.trace("EXIT");
-				return (EdgeEfp) edge;
-			}
-		}
-
-		logger.trace("EXIT");
-		return null;
-	}
-
-	/**
-	 * 
-	 * Check and add feature to edge.
-	 * 
-	 * @param requiredFeature
-	 *            Required feature with EFPs.
-	 * @param providedFeature
-	 *            Provided feature with EFPs.
-	 * @param name
-	 *            Feature name.
-	 * @param edge
-	 *            Edge where the feature belongs.
-	 */
-	private void checkAddEdgeFeature(CocaexDataFeature requiredFeature,
-			CocaexDataFeature providedFeature, String name, EdgeEfp edge) {
-		logger.trace("ENTRY");
-		EfpFeature tmpFeature = null;
-
-		// find out if the edge already has a features like the added one
-		for (EfpFeature oldFeature : edge.getFeatures()) {
-			// the edge contains the feature already
-			if (oldFeature.getName().equals(name)) {
-				tmpFeature = oldFeature;
-				break;
-			}
-		}
-
-		// an old feature
-		if (tmpFeature != null) {
-			tmpFeature = featureMap.get(name);
-
-			processEfpsToFeature(requiredFeature, providedFeature, tmpFeature,
-					edge);
-		} else { // add new feature to edge
-			tmpFeature = new EfpFeature(name);
-			
-			// preset the OK state
-			tmpFeature.setFeatureStatus(MatchingResult.OK.toString());
-
-			processEfpsToFeature(requiredFeature, providedFeature, tmpFeature,
-					edge);
-
-			edge.getFeatures().add(tmpFeature);
-			featureMap.put(name, tmpFeature);
-		}
-		logger.trace("EXIT");
-	}
-
-	/**
-	 * 
-	 * Prepare process of adding EFP values to existing feature.
-	 * 
-	 * @param requiredFeature
-	 *            Required feature with EFPs.
-	 * @param providedFeature
-	 *            Provided feature with EFPs.
-	 * @param feature
-	 *            Existing feature.
-	 * @param edge
-	 *            Edge where the EFPs with feature belong.
-	 */
-	private void processEfpsToFeature(CocaexDataFeature requiredFeature,
-			CocaexDataFeature providedFeature, EfpFeature feature, EdgeEfp edge) {
-		logger.trace("ENTRY");
-
-		MatchingResult result = checkAddFeatureEfp(requiredFeature,
-				providedFeature, feature);
-
-		if (!result.equals(MatchingResult.OK)) {
-			edge.setEdgeStatusOk(false);
-			feature.setFeatureStatus(result.toString());
-		} 
-		
-		logger.trace("EXIT");
-	}
-
-	/**
-	 * 
-	 * Check and add EFPs to an existing feature.
-	 * 
-	 * @param requiredFeature
-	 *            Required feature with EFPs.
-	 * @param providedFeature
-	 *            Provided feature with EFPs.
-	 * @param feature
-	 *            Existing feature.
-	 * @return Result of EFPs comparison. OK/MISSING/ERROR
-	 */
-	private MatchingResult checkAddFeatureEfp(
-			CocaexDataFeature requiredFeature,
-			CocaexDataFeature providedFeature, EfpFeature feature) {
-		logger.trace("ENTRY");
-		final String defaultValue = "No value";
-
-		MatchingResult output = MatchingResult.OK;
-
-		// all EFPs bound to this feature
-		for (int i = 0; i < requiredFeature.getEfps().size(); i++) {
-			EfpComparison efpCmp = new EfpComparison();
-
-			CocaexDataEfp firstEfp = requiredFeature.getEfps().get(i);
-			CocaexDataEfp secondEfp = providedFeature.getEfps().get(i);
-
-			// set real values
-			if (firstEfp.getEfpValue() != null) {
-				efpCmp.setLeftEfpValue(firstEfp.getEfpValue().toString());
-			} else {
-				efpCmp.setLeftEfpValue(defaultValue);
-			}
-
-			if (secondEfp.getEfpValue() != null) {
-				efpCmp.setRightEfpValue(secondEfp.getEfpValue().toString());
-			} else {
-				efpCmp.setRightEfpValue(defaultValue);
-			}
-
-			efpCmp.setTypeName(firstEfp.getEfpValueTypeName());
-			efpCmp.setEfpName(firstEfp.getEfpName());
-			efpCmp.setComparisonStatus(firstEfp.getTypeError().name());
-
-			// at least one efp is not OK
-			if (!firstEfp.getTypeError().equals(MatchingResult.OK)) {
-				output = firstEfp.getTypeError();
-			}
-
-			feature.getEfps().add(efpCmp);
-		}
-		logger.trace("EXIT");
-
-		return output;
-	}
-}
+//package cz.zcu.kiv.offscreen.graph.creator;
+//
+//import java.util.ArrayList;
+//import java.util.HashMap;
+//import java.util.List;
+//import java.util.Map;
+//
+//import org.apache.log4j.Logger;
+//
+//import cz.zcu.kiv.efps.comparator.result.EfpEvalResult.MatchingResult;
+//import cz.zcu.kiv.offscreen.api.EdgeInterface;
+//import cz.zcu.kiv.offscreen.api.GraphInterface;
+//import cz.zcu.kiv.offscreen.api.VertexInterface;
+//import cz.zcu.kiv.offscreen.data.efpportal.CocaexData;
+//import cz.zcu.kiv.offscreen.data.efpportal.CocaexDataEfp;
+//import cz.zcu.kiv.offscreen.data.efpportal.CocaexDataFeature;
+//import cz.zcu.kiv.offscreen.data.efpportal.CocaexWrapper;
+//import cz.zcu.kiv.offscreen.graph.EdgeEfp;
+//import cz.zcu.kiv.offscreen.graph.GraphImpl;
+//import cz.zcu.kiv.offscreen.graph.VertexEfp;
+//import cz.zcu.kiv.offscreen.graph.efp.EfpComparison;
+//import cz.zcu.kiv.offscreen.graph.efp.EfpFeature;
+//
+///**
+// *
+// * Transforms data obtained in form of Map<String, CocaexData> to
+// * cz.zcu.kiv.offscreen.api.GraphInterface.
+// *
+// * @author Jiri Loudil
+// *
+// */
+//public class EfpGraphTransfomer {
+//
+//	private final String DELIMITER = ";";
+//
+//	/**
+//	 * Output data format.
+//	 */
+//	private GraphInterface graph = null;
+//
+//	/**
+//	 * Input data format.
+//	 */
+//	private Map<String, CocaexData> resultData = null;
+//
+//	private Map<String, String> resultFeaturesMapping = null;
+//
+//	private Map<String, String> resultEfpsMapping = null;
+//
+//	/**
+//	 * Already used vertices.
+//	 */
+//	private Map<String, VertexInterface> vertexMap;
+//
+//	/**
+//	 * Already used features.
+//	 */
+//	private Map<String, EfpFeature> featureMap;
+//
+//	/**
+//	 * Logging.
+//	 */
+//	private Logger logger = Logger.getLogger(EfpGraphTransfomer.class);
+//
+//	/**
+//	 * New transformer from input data.
+//	 *
+//	 * @param efpportalResultsWrapper
+//	 *            Input data in from of EfpPortal app.
+//	 */
+//	public EfpGraphTransfomer(CocaexWrapper efpportalResultsWrapper) {
+//		logger.trace("ENTRY");
+//		this.graph = new GraphImpl();
+//
+//		this.resultData = efpportalResultsWrapper.getData();
+//		this.resultEfpsMapping = efpportalResultsWrapper.getEfpMappings();
+//		this.resultFeaturesMapping = efpportalResultsWrapper
+//				.getFeatureMappings();
+//
+//		this.vertexMap = new HashMap<String, VertexInterface>();
+//		this.featureMap = new HashMap<String, EfpFeature>();
+//
+//		logger.trace("EXIT");
+//	}
+//
+//	/**
+//	 * Generates the graph with vertices and edges.
+//	 *
+//	 * @return graph
+//	 */
+//	public GraphInterface transform() {
+//		logger.trace("ENTRY");
+//		this.generateVertices();
+//		this.generateEdges();
+//
+//		// set proper feature and efp names
+//		this.setNamesInsteadOfNumbers();
+//		logger.trace("EXIT");
+//
+//		return this.graph;
+//	}
+//
+//	/**
+//	 * Substitute ID for the proper name string.
+//	 */
+//	private void setNamesInsteadOfNumbers() {
+//		logger.trace("ENTRY");
+//
+//		List<EdgeInterface> edges = graph.getEdges();
+//
+//		for (EdgeInterface edgeInterface : edges) {
+//			ArrayList<EfpFeature> features = ((EdgeEfp) edgeInterface)
+//					.getFeatures();
+//
+//			for (EfpFeature efpFeature : features) {
+//				// substitute ID for the true name from the feature mapping
+//				String tmpFeatureName = resultFeaturesMapping.get(efpFeature.getName());
+//
+//				efpFeature.setName(tmpFeatureName.split(DELIMITER)[1]);
+//
+//				ArrayList<EfpComparison> efps = efpFeature.getEfps();
+//
+//				for (EfpComparison efpComparison : efps) {
+//					// substitute ID for the true name from the efps mapping
+//					efpComparison.setEfpName(resultEfpsMapping
+//							.get(efpComparison.getEfpName()));
+//				}
+//			}
+//		}
+//
+//		logger.trace("EXIT");
+//	}
+//
+//	/**
+//	 * Generate vertices for this graph.
+//	 */
+//	private void generateVertices() {
+//		logger.trace("ENTRY");
+//
+//		int id = 0;
+//		VertexEfp vertex;
+//
+//		for (Map.Entry<String, CocaexData> tmpData : resultData.entrySet()) {
+//			id++;
+//
+//			vertex = new VertexEfp(id, tmpData.getKey(), tmpData.getKey());
+//
+//			this.graph.addVertex(tmpData.getKey(), vertex);
+//			this.vertexMap.put(tmpData.getKey(), vertex);
+//		}
+//
+//		logger.trace("EXIT");
+//	}
+//
+//	/**
+//	 * Generate edges for this graph.
+//	 */
+//	private void generateEdges() {
+//		logger.trace("ENTRY");
+//
+//		int id = 0;
+//		String from, to;
+//		CocaexData currentEvaluatedVertexData;
+//
+//		for (Map.Entry<String, VertexInterface> currentVertex : vertexMap
+//				.entrySet()) {
+//			currentEvaluatedVertexData = resultData.get(currentVertex.getKey());
+//
+//			to = currentVertex.getKey();
+//
+//			// all required features FROM
+//			for (Map.Entry<String, CocaexDataFeature> tmpRequired : currentEvaluatedVertexData
+//					.getRequiredFeatures().entrySet()) {
+//
+//				String requiredFeatureName = this.resultFeaturesMapping
+//						.get(tmpRequired.getKey());
+//
+//				// get feature name, its first part is component name
+//				String[] requiredSplits = requiredFeatureName.split(DELIMITER);
+//
+//				// not-connected ones are left over
+//				if (!requiredSplits[0].isEmpty()) {
+//
+//					// vertex from == vertex to -> we dont want that...
+//					if (requiredSplits[0].equals(currentVertex.getKey())) {
+//						continue;
+//					}
+//
+//					// find corresponding feature on the TO vertex
+//					CocaexData otherVertexData = resultData
+//							.get(requiredSplits[0]);
+//					CocaexDataFeature otherVertexFeature = null;
+//
+//					// go through all features of the TO
+//					for (Map.Entry<String, CocaexDataFeature> tmpProvided : otherVertexData
+//							.getProvidedFeatures().entrySet()) {
+//						String providedFeatureName = this.resultFeaturesMapping
+//								.get(tmpProvided.getKey());
+//
+//						String[] providedSplits = providedFeatureName
+//								.split(DELIMITER);
+//
+//						// not-connected ones are left over
+//						if (providedSplits[0].isEmpty()) {
+//							continue;
+//						}
+//
+//						// found matching feature between TO and FROM
+//						if (providedSplits[0].equals(currentVertex.getKey())
+//								&& providedSplits[1].equals(requiredSplits[1])) {
+//							otherVertexFeature = tmpProvided.getValue();
+//						}
+//					}
+//
+//					from = requiredSplits[0];
+//
+//					EdgeEfp edge = findEdgeInGraph(from, to);
+//
+//					// add new edge
+//					if (edge == null) {
+//						edge = new EdgeEfp(++id, from, to);
+//						// from to
+//						checkAddEdgeFeature(tmpRequired.getValue(),
+//								otherVertexFeature, tmpRequired.getKey(), edge);
+//
+//						this.graph.addEdge(edge);
+//					} else {
+//						// add a feature to an old edge only
+//						checkAddEdgeFeature(tmpRequired.getValue(),
+//								otherVertexFeature, tmpRequired.getKey(), edge);
+//					}
+//				}
+//
+//			}
+//		}
+//
+//		logger.trace("EXIT");
+//	}
+//
+//	/**
+//	 *
+//	 * Find an existing edge in graph.
+//	 *
+//	 * @param from
+//	 *            Name of start vertex.
+//	 * @param to
+//	 *            name of end vertex.
+//	 * @return Null if not found, edge otherwise.
+//	 */
+//	private EdgeEfp findEdgeInGraph(String from, String to) {
+//		logger.trace("ENTRY");
+//		List<EdgeInterface> tmpEdges = this.graph.getEdges();
+//
+//		for (EdgeInterface edge : tmpEdges) {
+//			// found old edge
+//			if (edge.getFrom().equals(from) && edge.getTo().equals(to)) {
+//				logger.trace("EXIT");
+//				return (EdgeEfp) edge;
+//			}
+//		}
+//
+//		logger.trace("EXIT");
+//		return null;
+//	}
+//
+//	/**
+//	 *
+//	 * Check and add feature to edge.
+//	 *
+//	 * @param requiredFeature
+//	 *            Required feature with EFPs.
+//	 * @param providedFeature
+//	 *            Provided feature with EFPs.
+//	 * @param name
+//	 *            Feature name.
+//	 * @param edge
+//	 *            Edge where the feature belongs.
+//	 */
+//	private void checkAddEdgeFeature(CocaexDataFeature requiredFeature,
+//			CocaexDataFeature providedFeature, String name, EdgeEfp edge) {
+//		logger.trace("ENTRY");
+//		EfpFeature tmpFeature = null;
+//
+//		// find out if the edge already has a features like the added one
+//		for (EfpFeature oldFeature : edge.getFeatures()) {
+//			// the edge contains the feature already
+//			if (oldFeature.getName().equals(name)) {
+//				tmpFeature = oldFeature;
+//				break;
+//			}
+//		}
+//
+//		// an old feature
+//		if (tmpFeature != null) {
+//			tmpFeature = featureMap.get(name);
+//
+//			processEfpsToFeature(requiredFeature, providedFeature, tmpFeature,
+//					edge);
+//		} else { // add new feature to edge
+//			tmpFeature = new EfpFeature(name);
+//
+//			// preset the OK state
+//			tmpFeature.setFeatureStatus(MatchingResult.OK.toString());
+//
+//			processEfpsToFeature(requiredFeature, providedFeature, tmpFeature,
+//					edge);
+//
+//			edge.getFeatures().add(tmpFeature);
+//			featureMap.put(name, tmpFeature);
+//		}
+//		logger.trace("EXIT");
+//	}
+//
+//	/**
+//	 *
+//	 * Prepare process of adding EFP values to existing feature.
+//	 *
+//	 * @param requiredFeature
+//	 *            Required feature with EFPs.
+//	 * @param providedFeature
+//	 *            Provided feature with EFPs.
+//	 * @param feature
+//	 *            Existing feature.
+//	 * @param edge
+//	 *            Edge where the EFPs with feature belong.
+//	 */
+//	private void processEfpsToFeature(CocaexDataFeature requiredFeature,
+//			CocaexDataFeature providedFeature, EfpFeature feature, EdgeEfp edge) {
+//		logger.trace("ENTRY");
+//
+//		MatchingResult result = checkAddFeatureEfp(requiredFeature,
+//				providedFeature, feature);
+//
+//		if (!result.equals(MatchingResult.OK)) {
+//			edge.setEdgeStatusOk(false);
+//			feature.setFeatureStatus(result.toString());
+//		}
+//
+//		logger.trace("EXIT");
+//	}
+//
+//	/**
+//	 *
+//	 * Check and add EFPs to an existing feature.
+//	 *
+//	 * @param requiredFeature
+//	 *            Required feature with EFPs.
+//	 * @param providedFeature
+//	 *            Provided feature with EFPs.
+//	 * @param feature
+//	 *            Existing feature.
+//	 * @return Result of EFPs comparison. OK/MISSING/ERROR
+//	 */
+//	private MatchingResult checkAddFeatureEfp(
+//			CocaexDataFeature requiredFeature,
+//			CocaexDataFeature providedFeature, EfpFeature feature) {
+//		logger.trace("ENTRY");
+//		final String defaultValue = "No value";
+//
+//		MatchingResult output = MatchingResult.OK;
+//
+//		// all EFPs bound to this feature
+//		for (int i = 0; i < requiredFeature.getEfps().size(); i++) {
+//			EfpComparison efpCmp = new EfpComparison();
+//
+//			CocaexDataEfp firstEfp = requiredFeature.getEfps().get(i);
+//			CocaexDataEfp secondEfp = providedFeature.getEfps().get(i);
+//
+//			// set real values
+//			if (firstEfp.getEfpValue() != null) {
+//				efpCmp.setLeftEfpValue(firstEfp.getEfpValue().toString());
+//			} else {
+//				efpCmp.setLeftEfpValue(defaultValue);
+//			}
+//
+//			if (secondEfp.getEfpValue() != null) {
+//				efpCmp.setRightEfpValue(secondEfp.getEfpValue().toString());
+//			} else {
+//				efpCmp.setRightEfpValue(defaultValue);
+//			}
+//
+//			efpCmp.setTypeName(firstEfp.getEfpValueTypeName());
+//			efpCmp.setEfpName(firstEfp.getEfpName());
+//			efpCmp.setComparisonStatus(firstEfp.getTypeError().name());
+//
+//			// at least one efp is not OK
+//			if (!firstEfp.getTypeError().equals(MatchingResult.OK)) {
+//				output = firstEfp.getTypeError();
+//			}
+//
+//			feature.getEfps().add(efpCmp);
+//		}
+//		logger.trace("EXIT");
+//
+//		return output;
+//	}
+//}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/AttributeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/AttributeFilter.java
new file mode 100644
index 0000000..7dcda7b
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/AttributeFilter.java
@@ -0,0 +1,43 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import java.util.HashMap;
+
+public class AttributeFilter {
+    private HashMap<Integer, NumberAttributeFilter> numberFilters = new HashMap<Integer, NumberAttributeFilter>();
+    private HashMap<Integer, EnumAttributeFilter> enumFilters = new HashMap<Integer, EnumAttributeFilter>();
+    private HashMap<Integer, DateAttributeFilter> dateFilters = new HashMap<Integer, DateAttributeFilter>();
+    private HashMap<Integer, StringAttributeFilter> stringFilters = new HashMap<Integer, StringAttributeFilter>();
+
+
+    public void addNumberFilter(int attrTypeIndex, NumberAttributeFilter filter) {
+        numberFilters.put(attrTypeIndex, filter);
+    }
+
+    public NumberAttributeFilter getNumberFilter(int attrTypeIndex) {
+        return numberFilters.get(attrTypeIndex);
+    }
+
+    public void addEnumFilter(int attrTypeIndex, EnumAttributeFilter filter) {
+        enumFilters.put(attrTypeIndex, filter);
+    }
+
+    public EnumAttributeFilter getEnumFilter(int attrTypeIndex) {
+        return enumFilters.get(attrTypeIndex);
+    }
+
+    public void addDateFilter(int attrTypeIndex, DateAttributeFilter filter) {
+        dateFilters.put(attrTypeIndex, filter);
+    }
+
+    public DateAttributeFilter getDateFilter(int attrTypeIndex) {
+        return dateFilters.get(attrTypeIndex);
+    }
+
+    public void addStringFilter(int attrTypeIndex, StringAttributeFilter filter) {
+        stringFilters.put(attrTypeIndex, filter);
+    }
+
+    public StringAttributeFilter getStringFilter(int attrTypeIndex) {
+        return stringFilters.get(attrTypeIndex);
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/DateAttributeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/DateAttributeFilter.java
new file mode 100644
index 0000000..5296555
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/DateAttributeFilter.java
@@ -0,0 +1,57 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import java.util.Date;
+
+public class DateAttributeFilter implements ITypeAttributeFilter {
+    private Date min;
+    private Date max;
+    private boolean minInclusive;
+    private boolean maxInclusive;
+    private GraphFilter.DateMatchType matchType;
+
+    public DateAttributeFilter(Date min, Date max, boolean minInclusive, boolean maxInclusive, GraphFilter.DateMatchType matchType) {
+        this.min = min;
+        this.max = max;
+        this.minInclusive = minInclusive;
+        this.maxInclusive = maxInclusive;
+        this.matchType = matchType;
+    }
+
+    @Override
+    public boolean filter(Object value) {
+        Date date = (Date) value;
+        boolean result = false;
+
+        int cmpMin = -1;
+        int cmpMax = 1;
+
+        if (minInclusive) cmpMin = 0;
+        if (maxInclusive) cmpMax = 0;
+
+        if (min.compareTo(date) <= cmpMin && max.compareTo(date) >= cmpMax) {
+            result = true;
+        }
+
+        return (matchType == GraphFilter.DateMatchType.MATCHING) == result;
+    }
+
+    public Date getMin() {
+        return min;
+    }
+
+    public Date getMax() {
+        return max;
+    }
+
+    public boolean isMinInclusive() {
+        return minInclusive;
+    }
+
+    public boolean isMaxInclusive() {
+        return maxInclusive;
+    }
+
+    public GraphFilter.DateMatchType getMatchType() {
+        return matchType;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/EdgeArchetypeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/EdgeArchetypeFilter.java
new file mode 100644
index 0000000..cb5bcdf
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/EdgeArchetypeFilter.java
@@ -0,0 +1,15 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import cz.zcu.kiv.offscreen.graph.EdgeArchetypeInfo;
+
+import java.util.List;
+
+public class EdgeArchetypeFilter {
+    public List<EdgeArchetypeInfo> archetypeIndeces;
+    public GraphFilter.ArchetypeMatchType matchType;
+
+    public EdgeArchetypeFilter(List<EdgeArchetypeInfo> archetypeIndeces, GraphFilter.ArchetypeMatchType matchType) {
+        this.archetypeIndeces = archetypeIndeces;
+        this.matchType = matchType;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/EnumAttributeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/EnumAttributeFilter.java
new file mode 100644
index 0000000..1233ef7
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/EnumAttributeFilter.java
@@ -0,0 +1,61 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import java.util.List;
+
+public class EnumAttributeFilter implements ITypeAttributeFilter {
+    private List<Integer> valueIndices;
+    private GraphFilter.EnumMatchType matchType;
+
+    public EnumAttributeFilter(List<Integer> valueIndices, GraphFilter.EnumMatchType matchType) {
+        this.valueIndices = valueIndices;
+        this.matchType = matchType;
+    }
+
+    @Override
+    public boolean filter(Object value) {
+        boolean result = true;
+        List<Integer> val = (List<Integer>) value;
+
+        switch (matchType) {
+            case ANY:
+                for (int e : val) {
+                    if (valueIndices.contains(e)) {
+                        return true;
+                    }
+                }
+                result = false;
+                break;
+            case NONE:
+                for (int e : val) {
+                    if (valueIndices.contains(e)) {
+                        return false;
+                    }
+                }
+                result = true;
+                break;
+            case EXACT_MATCH:
+                for (int e : val) {
+                    if (!valueIndices.contains(e)) {
+                        return false;
+                    }
+                }
+                for (int e : valueIndices) {
+                    if (!val.contains(e)) {
+                        return false;
+                    }
+                }
+                result = true;
+                break;
+        }
+
+        return result;
+    }
+
+    public List<Integer> getValueIndices() {
+        return valueIndices;
+    }
+
+    public GraphFilter.EnumMatchType getMatchType() {
+        return matchType;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/GraphFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/GraphFilter.java
new file mode 100644
index 0000000..ce36932
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/GraphFilter.java
@@ -0,0 +1,226 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import cz.zcu.kiv.offscreen.graph.EdgeArchetypeInfo;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+
+public class GraphFilter {
+    public enum ArchetypeMatchType {
+        /**
+         * accepts all the archetypes in the list
+         */
+        MATCHING,
+
+        /**
+         * accepts all the available archetypes except those in the list
+         */
+        NON_MATCHING
+    }
+
+    public enum NumberMatchType {
+        /**
+         * accepts all numbers that belong to the interval
+         */
+        MATCHING,
+
+        /**
+         * accepts all numbers that are outside the interval
+         */
+        NON_MATCHING
+    }
+
+    public enum EnumMatchType {
+        /**
+         * accepts when the attribute has at least one of the values in the list
+         */
+        ANY,
+
+        /**
+         * accepts when the attribute has none of the values in the list
+         */
+        NONE,
+
+        /**
+         * accepts when the attribute has the exact values as the values in the list and none other
+         */
+        EXACT_MATCH
+    }
+
+    public enum DateMatchType {
+        /**
+         * accepts all dates that belong to the interval
+         */
+        MATCHING,
+
+        /**
+         * accepts all dates that are outside the interval
+         */
+        NON_MATCHING
+    }
+
+    public enum StringMatchType {
+        /**
+         * accepts strings that have the exact filter value
+         */
+        EXACT_MATCH,
+
+        /**
+         * accepts strings that have any value different from the filter value
+         */
+        EXACT_MISMATCH,
+
+        /**
+         * accepts strings that contain the filter value as a substring
+         */
+        CONTAINING,
+
+        /**
+         * accepts strings that do not contain the filter value as s substring
+         */
+        NON_CONTAINING,
+
+        /**
+         * accepts strings that are accepted by the regular expression defined by the filter value
+         */
+        REGULAR_EXPRESSION
+    }
+
+    private VertexArchetypeFilter vertexArchetypeFilter;
+    private EdgeArchetypeFilter edgeArchetypeFilter;
+
+    /**
+     * key is the vertex archetype index, value is the filter object
+     */
+    private HashMap<Integer, AttributeFilter> vertexAttributeFilters = new HashMap<>();
+
+    /**
+     * key is the edge archetype index, value is the filter object
+     */
+    private HashMap<Integer, AttributeFilter> edgeAttributeFilters = new HashMap<Integer, AttributeFilter>();
+
+    public AttributeFilter getVertexAttributeFilter(int archetypeIndex) {
+        return vertexAttributeFilters.get(archetypeIndex);
+    }
+
+    public AttributeFilter getEdgeAttributeFilter(int archetypeIndex) {
+        return edgeAttributeFilters.get(archetypeIndex);
+    }
+
+    public VertexArchetypeFilter getVertexArchetypeFilter() {
+        return vertexArchetypeFilter;
+    }
+
+    public EdgeArchetypeFilter getEdgeArchetypeFilter() {
+        return edgeArchetypeFilter;
+    }
+
+    public void setVertexArchetypeFilter(List<Integer> archetypeIndices, ArchetypeMatchType matchType) {
+        vertexArchetypeFilter = new VertexArchetypeFilter(archetypeIndices, matchType);
+    }
+
+    public void setEdgeArchetypeFilter(List<EdgeArchetypeInfo> archetypeIndices, ArchetypeMatchType matchType) {
+        edgeArchetypeFilter = new EdgeArchetypeFilter(archetypeIndices, matchType);
+    }
+
+    public void setVertexNumberAttributeFilter(int archetypeIndex, int attributeTypeIndex, BigDecimal min, BigDecimal max, boolean minInclusive, boolean maxInclusive, NumberMatchType matchType) {
+        AttributeFilter filter;
+        if (vertexAttributeFilters.containsKey(archetypeIndex)) {
+            filter = vertexAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            vertexAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addNumberFilter(attributeTypeIndex, new NumberAttributeFilter(min, max, minInclusive, maxInclusive, matchType));
+    }
+
+    public void setEdgeNumberAttributeFilter(int archetypeIndex, int attributeTypeIndex, BigDecimal min, BigDecimal max, boolean minInclusive, boolean maxInclusive, NumberMatchType matchType) {
+        AttributeFilter filter;
+        if (edgeAttributeFilters.containsKey(archetypeIndex)) {
+            filter = edgeAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            edgeAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addNumberFilter(attributeTypeIndex, new NumberAttributeFilter(min, max, minInclusive, maxInclusive, matchType));
+    }
+
+    public void setVertexEnumAttributeFilter(int archetypeIndex, int attributeTypeIndex, List<Integer> valueIndices, EnumMatchType matchType) {
+        AttributeFilter filter;
+        if (vertexAttributeFilters.containsKey(archetypeIndex)) {
+            filter = vertexAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            vertexAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addEnumFilter(attributeTypeIndex, new EnumAttributeFilter(valueIndices, matchType));
+    }
+
+    public void setEdgeEnumAttributeFilter(int archetypeIndex, int attributeTypeIndex, List<Integer> valueIndices, EnumMatchType matchType) {
+        AttributeFilter filter;
+        if (edgeAttributeFilters.containsKey(archetypeIndex)) {
+            filter = edgeAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            edgeAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addEnumFilter(attributeTypeIndex, new EnumAttributeFilter(valueIndices, matchType));
+    }
+
+    public void setVertexDateAttributeFilter(int archetypeIndex, int attributeTypeIndex, Date min, Date max, boolean minInclusive, boolean maxInclusive, DateMatchType matchType) {
+        AttributeFilter filter;
+        if (vertexAttributeFilters.containsKey(archetypeIndex)) {
+            filter = vertexAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            vertexAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addDateFilter(attributeTypeIndex, new DateAttributeFilter(min, max, minInclusive, maxInclusive, matchType));
+    }
+
+    public void setEdgeDateAttributeFilter(int archetypeIndex, int attributeTypeIndex, Date min, Date max, boolean minInclusive, boolean maxInclusive, DateMatchType matchType) {
+        AttributeFilter filter;
+        if (edgeAttributeFilters.containsKey(archetypeIndex)) {
+            filter = edgeAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            edgeAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addDateFilter(attributeTypeIndex, new DateAttributeFilter(min, max, minInclusive, maxInclusive, matchType));
+    }
+
+    public void setVertexStringAttributeFilter(int archetypeIndex, int attributeTypeIndex, String filterValue, StringMatchType matchType) {
+        AttributeFilter filter;
+        if (vertexAttributeFilters.containsKey(archetypeIndex)) {
+            filter = vertexAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            vertexAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addStringFilter(attributeTypeIndex, new StringAttributeFilter(filterValue, matchType));
+    }
+
+    public void setEdgeStringAttributeFilter(int archetypeIndex, int attributeTypeIndex, String filterValue, StringMatchType matchType) {
+        AttributeFilter filter;
+        if (edgeAttributeFilters.containsKey(archetypeIndex)) {
+            filter = edgeAttributeFilters.get(archetypeIndex);
+        } else {
+            filter = new AttributeFilter();
+            edgeAttributeFilters.put(archetypeIndex, filter);
+        }
+        filter.addStringFilter(attributeTypeIndex, new StringAttributeFilter(filterValue, matchType));
+    }
+
+    /*
+    advised filtering process:
+    first filter the archetypes using queries in the hash maps in GraphManager
+    then iterate through all vertices/edges that are left after the first step and for each vertex/edge do the following:
+     - use getVertex/EdgeAttributeFilter in GraphFilter to get the filer setting for the given archetype, this returns AttributeFilter
+     - iterate through all attributes of the vertex/edge and do the following:
+        - get the attribute data type and index
+        - use getString/Number/Enum/DateFilter in AttributeFilter to get the filter for the given attribute
+        - decide whether the attribute's value passes the filter and whether to keep the give vertex/edge or not
+     */
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/ITypeAttributeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/ITypeAttributeFilter.java
new file mode 100644
index 0000000..e28194f
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/ITypeAttributeFilter.java
@@ -0,0 +1,5 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+public interface ITypeAttributeFilter {
+    boolean filter(Object value);
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/NumberAttributeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/NumberAttributeFilter.java
new file mode 100644
index 0000000..3b67d2c
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/NumberAttributeFilter.java
@@ -0,0 +1,57 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import java.math.BigDecimal;
+
+public class NumberAttributeFilter implements ITypeAttributeFilter {
+    private BigDecimal min;
+    private BigDecimal max;
+    private boolean minInclusive;
+    private boolean maxInclusive;
+    private GraphFilter.NumberMatchType matchType;
+
+    public NumberAttributeFilter(BigDecimal min, BigDecimal max, boolean minInclusive, boolean maxInclusive, GraphFilter.NumberMatchType matchType) {
+        this.min = min;
+        this.max = max;
+        this.minInclusive = minInclusive;
+        this.maxInclusive = maxInclusive;
+        this.matchType = matchType;
+    }
+
+    @Override
+    public boolean filter(Object value) {
+        BigDecimal val = (BigDecimal) value;
+        boolean result = false;
+
+        int cmpMin = -1;
+        int cmpMax = 1;
+
+        if (minInclusive) cmpMin = 0;
+        if (maxInclusive) cmpMax = 0;
+
+        if (min.compareTo(val) <= cmpMin && max.compareTo(val) >= cmpMax) {
+            result = true;
+        }
+
+        return (matchType == GraphFilter.NumberMatchType.MATCHING) == result;
+    }
+
+    public BigDecimal getMin() {
+        return min;
+    }
+
+    public BigDecimal getMax() {
+        return max;
+    }
+
+    public boolean isMinInclusive() {
+        return minInclusive;
+    }
+
+    public boolean isMaxInclusive() {
+        return maxInclusive;
+    }
+
+    public GraphFilter.NumberMatchType getMatchType() {
+        return matchType;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/StringAttributeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/StringAttributeFilter.java
new file mode 100644
index 0000000..1280fd7
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/StringAttributeFilter.java
@@ -0,0 +1,50 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class StringAttributeFilter implements ITypeAttributeFilter {
+    private String filterValue;
+    private GraphFilter.StringMatchType matchType;
+
+    public StringAttributeFilter(String filterValue, GraphFilter.StringMatchType matchType) {
+        this.filterValue = filterValue;
+        this.matchType = matchType;
+    }
+
+    @Override
+    public boolean filter(Object value) {
+        String val = (String) value;
+        boolean result = false;
+
+        switch (matchType) {
+            case EXACT_MATCH:
+                if (val.equals(filterValue)) result = true;
+                break;
+            case EXACT_MISMATCH:
+                if (!val.equals(filterValue)) result = true;
+                break;
+            case CONTAINING:
+                if (val.contains(filterValue)) result = true;
+                break;
+            case NON_CONTAINING:
+                if (!val.contains(filterValue)) result = true;
+                break;
+            case REGULAR_EXPRESSION:
+                Pattern pattern = Pattern.compile(filterValue);
+                Matcher matcher = pattern.matcher(val);
+                if (matcher.find()) result = true;
+                break;
+        }
+
+        return result;
+    }
+
+    public String getFilterValue() {
+        return filterValue;
+    }
+
+    public GraphFilter.StringMatchType getMatchType() {
+        return matchType;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/filter/VertexArchetypeFilter.java b/sources/src/cz/zcu/kiv/offscreen/graph/filter/VertexArchetypeFilter.java
new file mode 100644
index 0000000..21f19ca
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/filter/VertexArchetypeFilter.java
@@ -0,0 +1,13 @@
+package cz.zcu.kiv.offscreen.graph.filter;
+
+import java.util.List;
+
+public class VertexArchetypeFilter {
+    public List<Integer> archetypeIndeces;
+    public GraphFilter.ArchetypeMatchType matchType;
+
+    public VertexArchetypeFilter(List<Integer> archetypeIndeces, GraphFilter.ArchetypeMatchType matchType) {
+        this.archetypeIndeces = archetypeIndeces;
+        this.matchType = matchType;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/loader/GraphJSONDataLoader.java b/sources/src/cz/zcu/kiv/offscreen/graph/loader/GraphJSONDataLoader.java
new file mode 100644
index 0000000..ae7b5d9
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/loader/GraphJSONDataLoader.java
@@ -0,0 +1,223 @@
+package cz.zcu.kiv.offscreen.graph.loader;
+
+import cz.zcu.kiv.offscreen.graph.Attribute;
+import cz.zcu.kiv.offscreen.graph.EdgeArchetypeInfo;
+import cz.zcu.kiv.offscreen.graph.GraphManager;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Class loads json file with graph data.
+ * @author Stepan Baratta
+ */
+public class GraphJSONDataLoader {
+
+    private File file;
+    private String loadedJSON;
+
+    private GraphManager graphManager;
+
+    /**
+     * stores archetypes of vertices, key is the vertex id, value is the index of its archetype
+     */
+    private HashMap<Integer, Integer> vertexArchetypes = new HashMap<Integer, Integer>();
+
+    static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+    public GraphJSONDataLoader(File file) {
+        this.file = file;
+    }
+
+    private void loadJSON() throws IOException {
+        loadedJSON = FileUtils.readFileToString(file, "UTF-8");
+    }
+
+    public GraphManager LoadData() throws IOException {
+        this.graphManager = new GraphManager();
+
+        loadJSON();
+        JSONObject json = JSONObject.fromObject(loadedJSON);
+
+        JSONArray attributeTypes = getLoadedAttributeTypes(json);
+
+        loadVertexArchetypes(json);
+
+        loadEdgeArchetypes(json);
+
+        loadVertices(attributeTypes, json);
+
+        loadEdges(attributeTypes, json);
+
+        return graphManager;
+    }
+
+    /**
+     * Returns the json array with the loaded attribute types.
+     * Adds the attributes to the list of all attribute types.
+     * @param json
+     * @return - Json array with the attribute types.
+     */
+    private JSONArray getLoadedAttributeTypes(JSONObject json) {
+        JSONArray attributeTypes = json.getJSONArray("attributeTypes");
+        for (int i = 0; i < attributeTypes.size(); i++) {
+            JSONObject attributeType = attributeTypes.getJSONObject(i);
+            String dataTypeString = attributeType.getString("dataType");
+            GraphManager.AttributeDataType dataType;
+            switch (dataTypeString) {
+                case "number": dataType = GraphManager.AttributeDataType.NUMBER; break;
+                case "date": dataType = GraphManager.AttributeDataType.DATE; break;
+                case "enum": dataType = GraphManager.AttributeDataType.ENUM; break;
+                default: dataType = GraphManager.AttributeDataType.STRING; break;
+            }
+            graphManager.addAttributeType(attributeType.getString("name"), dataType, attributeType.getString("text"));
+        }
+
+        return attributeTypes;
+    }
+
+    /**
+     * Loads the vertex archetypes from the json and adds them to all vertex archetypes.
+     * @param json
+     */
+    private void loadVertexArchetypes(JSONObject json) {
+        JSONArray vertexArchetypes = json.getJSONArray("vertexArchetypes");
+        for (int i = 0; i < vertexArchetypes.size(); i++) {
+            JSONObject vertexArchetype = vertexArchetypes.getJSONObject(i);
+
+            graphManager.addVertexArchetype(vertexArchetype.getString("name"), vertexArchetype.getString("text"));
+        }
+    }
+
+    /**
+     * Loads the edge archetypes from the json and adds them to all edge archetypes.
+     * @param json
+     */
+    private void loadEdgeArchetypes(JSONObject json) {
+        JSONArray edgeArchetypes = json.getJSONArray("edgeArchetypes");
+        for (int i = 0; i < edgeArchetypes.size(); i++) {
+            JSONObject edgeArchetype = edgeArchetypes.getJSONObject(i);
+
+            graphManager.addEdgeArchetype(edgeArchetype.getString("name"), edgeArchetype.getString("text"));
+        }
+    }
+
+    /**
+     * Loads the vertices from the json and adds them to the list of all vertices.
+     * @param attributeTypes - json array with the attribute types
+     * @param json
+     */
+    private void loadVertices(JSONArray attributeTypes, JSONObject json) {
+        JSONArray verticesObject = json.getJSONArray("vertices");
+        for (int i = 0; i < verticesObject.size(); i++) {
+            JSONObject vertexObject = verticesObject.getJSONObject(i);
+            String name = vertexObject.getString("title");
+            String text = vertexObject.getString("text");
+            int archetypeIndex = vertexObject.getInt("archetype");
+            int vertexId = vertexObject.getInt("id");
+            vertexArchetypes.put(vertexId, archetypeIndex);
+
+            JSONObject attributesObject = vertexObject.getJSONObject("attributes");
+            Map<Integer, Attribute> attributes = loadObjectAttributes(attributesObject, attributeTypes);
+
+            graphManager.addVertex(vertexId, name, text, archetypeIndex, attributes);
+        }
+    }
+
+    /**
+     * Loads the edges from the json and adds them to the list of all edges.
+     * @param attributeTypes - List of attributes
+     * @param json
+     */
+    private void loadEdges(JSONArray attributeTypes, JSONObject json) {
+        JSONArray edgesObject = json.getJSONArray("edges");
+        for (int i = 0; i < edgesObject.size(); i++) {
+            JSONObject edgeObject = edgesObject.getJSONObject(i);
+            int edgeId = edgeObject.getInt("id");
+            int from = edgeObject.getInt("from");
+            int to = edgeObject.getInt("to");
+            String text = edgeObject.getString("text");
+            int archetypeIndex = edgeObject.getInt("archetype");
+            int fromArchetypeIndex = vertexArchetypes.get(from);
+            int toArchetypeIndex = vertexArchetypes.get(to);
+
+            JSONObject attributesObject = edgeObject.getJSONObject("attributes");
+            Map<Integer, Attribute> attributes = loadObjectAttributes(attributesObject, attributeTypes);
+
+            EdgeArchetypeInfo archetypeInfo = new EdgeArchetypeInfo(fromArchetypeIndex, archetypeIndex, toArchetypeIndex);
+            graphManager.addEdge(edgeId, from, to, text, archetypeInfo, attributes);
+        }
+    }
+
+    /**
+     * Loads all the attributes for the json object.
+     * @param attributesObject - json object for which to get the attributes
+     * @param attributeTypes - All types of attributes
+     * @return Map of attributes for the json object
+     */
+    private Map<Integer, Attribute> loadObjectAttributes(JSONObject attributesObject, JSONArray attributeTypes) {
+        Map<Integer, Attribute> attributes = new HashMap<>();
+        for (Object attributeKey : attributesObject.keySet()) {
+            Object attrValue = loadAttributeFromObject((String)attributeKey, attributeTypes, attributesObject);
+
+            int attributeTypeIndex = Integer.parseInt((String)attributeKey);
+            attributes.put(attributeTypeIndex, new Attribute(attributeTypeIndex, attrValue));
+        }
+
+        return attributes;
+    }
+
+    /**
+     * Loads single attribute from the json object
+     * @param attributeIdString - Attribute id as key
+     * @param attributeTypes - All the attributes types
+     * @param attributesObject - Object containing all the attributes for the current object
+     * @return Value of the attribute
+     */
+    private Object loadAttributeFromObject(String attributeIdString, JSONArray attributeTypes, JSONObject attributesObject) {
+        int attributeId = Integer.parseInt(attributeIdString);
+        String attrType = attributeTypes.getJSONObject(attributeId).getString("dataType");
+        Object attrValue;
+        switch (attrType) {
+            case "number":
+                String val = attributesObject.getString(attributeIdString);
+                attrValue = new BigDecimal(val);
+                break;
+            case "date":
+                String dateStr = attributesObject.getString(attributeIdString);
+                SimpleDateFormat format = new SimpleDateFormat(GraphJSONDataLoader.DATETIME_FORMAT);
+                attrValue = format.parse(dateStr, new ParsePosition(0));
+                break;
+            case "enum":
+                List<String> enumValues = new ArrayList<>();
+                JSONArray enumValuesArray = attributesObject.optJSONArray(attributeIdString);
+                if (enumValuesArray == null) {
+                    enumValues.add(attributesObject.getString(attributeIdString)); // Only one value present
+                } else {
+                    for (int j = 0; j < enumValuesArray.size(); j++) {
+                        enumValues.add(enumValuesArray.getString(j));
+                    }
+                }
+
+                graphManager.addUniquePossibleAttributeValues(attributeId, enumValues);
+                attrValue = graphManager.getEnumPositionsForAttrIndex(attributeId, enumValues);
+
+                break;
+            default:
+                attrValue = attributesObject.getString(attributeIdString);
+                break;
+        }
+
+        return attrValue;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/graph/loader/JSONConfigLoader.java b/sources/src/cz/zcu/kiv/offscreen/graph/loader/JSONConfigLoader.java
new file mode 100644
index 0000000..5a6faa1
--- /dev/null
+++ b/sources/src/cz/zcu/kiv/offscreen/graph/loader/JSONConfigLoader.java
@@ -0,0 +1,380 @@
+package cz.zcu.kiv.offscreen.graph.loader;
+
+import cz.zcu.kiv.offscreen.AttributeType;
+import cz.zcu.kiv.offscreen.graph.EdgeArchetypeInfo;
+import cz.zcu.kiv.offscreen.graph.GraphManager;
+import cz.zcu.kiv.offscreen.graph.filter.*;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * Class is used to load the configuration file from disk.
+ * The configuration file contains default filters, svgs for archetype icons
+ * and other configurable application properties.
+ *
+ * @author Stepan Baratta
+ */
+public class JSONConfigLoader {
+
+    private GraphManager graphManager;
+    private JSONObject json;
+
+    /**
+     * Path to the directory with configuration file.
+     */
+    private String pathToConfig;
+
+    public static String configFilename = "config.json";
+
+    public JSONConfigLoader(GraphManager graphManager, String pathToConfig) {
+        this.graphManager = graphManager;
+        this.pathToConfig = pathToConfig;
+    }
+
+    /**
+     * Loads the default filter into the {@code GraphFilter} object.
+     * @return {@code GraphFilter} with set values of the default filter.
+     */
+    public GraphFilter loadDefaultFilter() {
+        GraphFilter filter = new GraphFilter();
+
+        try {
+            //String filterJson = FileUtils.readFileToString(new File("D:\\aswi-git\\aswi\\config\\empty_filter.json"), "UTF-8");
+            String filterJson = FileUtils.readFileToString(new File(pathToConfig + "\\" + configFilename), "UTF-8");
+
+            json = JSONObject.fromObject(filterJson);
+
+            JSONObject defaultFilter = json.getJSONObject("defaultFilter");
+            JSONObject vertexArchetypeFilter = defaultFilter.getJSONObject("vertexArchetypeFilter");
+
+            processVertexArchetypeFilters(filter, vertexArchetypeFilter);
+
+            JSONObject edgeArchetypeFilter = defaultFilter.getJSONObject("edgeArchetypeFilter");
+
+            processEdgeArchetypeFilters(filter, edgeArchetypeFilter);
+
+            Object[][] vertexAttributeFilterStrings = loadAttributeFilters(defaultFilter.getJSONArray("vertexAttributeFilters"));
+
+            createVertexAttributeFilters(filter, vertexAttributeFilterStrings);
+
+            Object[][] edgeAttributeFilterStrings = loadAttributeFilters(defaultFilter.getJSONArray("edgeAttributeFilters"));
+
+            createEdgeAttributeFilters(filter, edgeAttributeFilterStrings);
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return filter;
+    }
+
+    /**
+     * Loads the edge archetypes from the json object.
+     * @param filter - Filter to be used.
+     * @param edgeArchetypeFilter - Json object containing the edge archetype filters.
+     */
+    private void processEdgeArchetypeFilters(GraphFilter filter, JSONObject edgeArchetypeFilter) {
+        JSONArray edgeFilterArchetypes = edgeArchetypeFilter.getJSONArray("archetypes");
+        String[][][] edgeArchetypeStrings = new String[edgeFilterArchetypes.size()][][];
+
+        for (int i = 0; i < edgeFilterArchetypes.size(); i++) {
+            edgeArchetypeStrings[i] = new String[3][];
+
+            JSONObject edgeFilterArchetype = edgeFilterArchetypes.getJSONObject(i);
+            JSONArray fromArchetypes = edgeFilterArchetype.getJSONArray("fromArchetypes");
+
+            edgeArchetypeStrings[i][0] = new String[fromArchetypes.size()];
+            for (int j = 0; j < fromArchetypes.size(); j++) {
+                edgeArchetypeStrings[i][0][j] = fromArchetypes.getString(j);
+            }
+
+            JSONArray edgeArchetypes = edgeFilterArchetype.getJSONArray("edgeArchetypes");
+            edgeArchetypeStrings[i][1] = new String[edgeArchetypes.size()];
+            for (int j = 0; j < edgeArchetypes.size(); j++) {
+                edgeArchetypeStrings[i][1][j] = edgeArchetypes.getString(j);
+            }
+
+            JSONArray toArchetypes = edgeFilterArchetype.getJSONArray("toArchetypes");
+            edgeArchetypeStrings[i][2] = new String[toArchetypes.size()];
+            for (int j = 0; j < toArchetypes.size(); j++) {
+                edgeArchetypeStrings[i][2][j] = toArchetypes.getString(j);
+            }
+        }
+
+        String edgeArchetypeMatchType = edgeArchetypeFilter.getString("matchType");
+
+        List<EdgeArchetypeInfo> edgeArchetypeFilterList = createEdgeArchetypeFilterList(edgeArchetypeStrings);
+
+        filter.setEdgeArchetypeFilter(edgeArchetypeFilterList, GraphFilter.ArchetypeMatchType.valueOf(edgeArchetypeMatchType.toUpperCase()));
+    }
+
+    /**
+     * Creates edge archetype filter list.
+     * @param edgeArchetypeStrings -
+     * @return
+     */
+    private List<EdgeArchetypeInfo> createEdgeArchetypeFilterList(String[][][] edgeArchetypeStrings) {
+        List<EdgeArchetypeInfo> edgeArchetypeFilterList = new ArrayList<>();
+        for (EdgeArchetypeInfo info : graphManager.edges.keySet()) {
+            for (String[][] edgeArchetypeString : edgeArchetypeStrings) {
+                boolean fromMatch = false;
+                boolean edgeMatch = false;
+                boolean toMatch = false;
+                String fromArchetype = graphManager.vertexArchetypes.get(info.fromArchetypeIndex).name;
+                String edgeArchetype = graphManager.edgeArchetypes.get(info.edgeArchetypeIndex).name;
+                String toArchetype = graphManager.vertexArchetypes.get(info.toArchetypeIndex).name;
+                for (int j = 0; j < edgeArchetypeString[0].length; j++) {
+                    fromMatch = (fromMatch || fromArchetype.equals(edgeArchetypeString[0][j]));
+                }
+                for (int j = 0; j < edgeArchetypeString[1].length; j++) {
+                    edgeMatch = (edgeMatch || edgeArchetype.equals(edgeArchetypeString[1][j]));
+                }
+                for (int j = 0; j < edgeArchetypeString[2].length; j++) {
+                    toMatch = (toMatch || toArchetype.equals(edgeArchetypeString[2][j]));
+                }
+                if (fromMatch && edgeMatch && toMatch) {
+                    edgeArchetypeFilterList.add(new EdgeArchetypeInfo(info.fromArchetypeIndex, info.edgeArchetypeIndex, info.toArchetypeIndex));
+                }
+            }
+        }
+        return edgeArchetypeFilterList;
+    }
+
+    /**
+     * Loads the vertex archetypes from the json object.
+     * @param filter - Filter to be used.
+     * @param vertexArchetypeFilter - Json object with the vertex archetype filters.
+     */
+    private void processVertexArchetypeFilters(GraphFilter filter, JSONObject vertexArchetypeFilter) {
+        JSONArray archetypes = vertexArchetypeFilter.getJSONArray("archetypes");
+
+        String[] vertexArchetypeStrings = new String[archetypes.size()];
+        for (int i = 0; i < archetypes.size(); i++) {
+            vertexArchetypeStrings[i] = archetypes.get(i).toString();
+        }
+
+        List<Integer> vertexArchetypeFilterList = new ArrayList<>();
+        for (int i = 0; i < graphManager.vertexArchetypes.size(); i++) {
+            for (String vertexArchetypeString : vertexArchetypeStrings) {
+                if (graphManager.vertexArchetypes.get(i).name.equals(vertexArchetypeString)) {
+                    vertexArchetypeFilterList.add(i);
+                }
+            }
+        }
+
+        String vertexArchetypeMatchType = vertexArchetypeFilter.getString("matchType");
+
+        filter.setVertexArchetypeFilter(vertexArchetypeFilterList, GraphFilter.ArchetypeMatchType.valueOf(vertexArchetypeMatchType.toUpperCase()));
+    }
+
+    /**
+     * Loads attribute filters from json array.
+     * @param attributeFilters - Json array with the attribute filters.
+     */
+    private Object[][] loadAttributeFilters(JSONArray attributeFilters) {
+        Object[][] attributeFilterStrings = new Object[attributeFilters.size()][3];
+
+        for (int i = 0; i < attributeFilters.size(); i++) {
+            JSONObject attributeFilter = attributeFilters.getJSONObject(i);
+            String archetypeName = attributeFilter.getString("archetype");
+            String attributeName = attributeFilter.getString("attributeName");
+
+            attributeFilterStrings[i][0] = archetypeName;
+            attributeFilterStrings[i][1] = attributeName;
+
+            JSONObject attributeFilterInfo = attributeFilter.getJSONObject("filter");
+            String filterMatchType = attributeFilterInfo.getString("matchType");
+
+            AttributeType attrType = graphManager.getAttributeDataTypeByName(attributeName);
+            switch (attrType.dataType) {
+                case ENUM:
+                    attributeFilterStrings[i][2] = getEnumAttributeFilter(attributeName, attributeFilterInfo, GraphFilter.EnumMatchType.valueOf(filterMatchType.toUpperCase()));
+                    break;
+                case NUMBER:
+                    attributeFilterStrings[i][2] = getNumberAttributeFilter(attributeFilterInfo, GraphFilter.NumberMatchType.valueOf(filterMatchType.toUpperCase()));
+                    break;
+                case DATE:
+                    attributeFilterStrings[i][2] = getDateAttributeFilter(attributeFilterInfo, GraphFilter.DateMatchType.valueOf(filterMatchType.toUpperCase()));
+                    break;
+                case STRING:
+                    attributeFilterStrings[i][2] = getStringAttributeFilter(attributeFilterInfo, GraphFilter.StringMatchType.valueOf(filterMatchType.toUpperCase()));
+                    break;
+            }
+        }
+
+        return attributeFilterStrings;
+    }
+
+    /**
+     * Sets the filtering objects from vertexAttributeFilterStrings to the graph filter object.
+     * @param filter - Graph filter object
+     * @param vertexAttributeFilterStrings - Array with attribute filter parameters (Archetype name, attribute name, filter object)
+     */
+    private void createVertexAttributeFilters(GraphFilter filter, Object[][] vertexAttributeFilterStrings) {
+        for (Object[] vertexAttributeFilterString : vertexAttributeFilterStrings) {
+            int archetypeIndex = graphManager.getVertexArchetypeIndex(vertexAttributeFilterString[0].toString());
+            int attributeIndex = graphManager.getAttributeIndex(vertexAttributeFilterString[1].toString());
+            GraphManager.AttributeDataType type = graphManager.attributeTypes.get(attributeIndex).dataType;
+            switch (type) {
+                case NUMBER:
+                    NumberAttributeFilter nf = (NumberAttributeFilter) vertexAttributeFilterString[2];
+                    filter.setVertexNumberAttributeFilter(archetypeIndex, attributeIndex, nf.getMin(), nf.getMax(), nf.isMinInclusive(), nf.isMaxInclusive(), nf.getMatchType());
+                    break;
+                case DATE:
+                    DateAttributeFilter df = (DateAttributeFilter) vertexAttributeFilterString[2];
+                    filter.setVertexDateAttributeFilter(archetypeIndex, attributeIndex, df.getMin(), df.getMax(), df.isMinInclusive(), df.isMaxInclusive(), df.getMatchType());
+                    break;
+                case STRING:
+                    StringAttributeFilter sf = (StringAttributeFilter) vertexAttributeFilterString[2];
+                    filter.setVertexStringAttributeFilter(archetypeIndex, attributeIndex, sf.getFilterValue(), sf.getMatchType());
+                    break;
+                case ENUM:
+                    EnumAttributeFilter ef = (EnumAttributeFilter) vertexAttributeFilterString[2];
+                    filter.setVertexEnumAttributeFilter(archetypeIndex, attributeIndex, ef.getValueIndices(), ef.getMatchType());
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Sets the filtering objects from edgeAttributeFilterStrings to the graph filter object
+     * @param filter - Graph filter object
+     * @param edgeAttributeFilterStrings - Array with attribute filter parameters (Archetype name, attribute name, filter object)
+     */
+    private void createEdgeAttributeFilters(GraphFilter filter, Object[][] edgeAttributeFilterStrings) {
+        for (Object[] edgeAttributeFilterString : edgeAttributeFilterStrings) {
+            int archetypeIndex = graphManager.getEdgeArchetypeIndex(edgeAttributeFilterString[0].toString());
+            int attributeIndex = graphManager.getAttributeIndex(edgeAttributeFilterString[1].toString());
+            GraphManager.AttributeDataType type = graphManager.attributeTypes.get(attributeIndex).dataType;
+            switch (type) {
+                case NUMBER:
+                    NumberAttributeFilter nf = (NumberAttributeFilter) edgeAttributeFilterString[2];
+                    filter.setEdgeNumberAttributeFilter(archetypeIndex, attributeIndex, nf.getMin(), nf.getMax(), nf.isMinInclusive(), nf.isMaxInclusive(), nf.getMatchType());
+                    break;
+                case DATE:
+                    DateAttributeFilter df = (DateAttributeFilter) edgeAttributeFilterString[2];
+                    filter.setEdgeDateAttributeFilter(archetypeIndex, attributeIndex, df.getMin(), df.getMax(), df.isMinInclusive(), df.isMaxInclusive(), df.getMatchType());
+                    break;
+                case STRING:
+                    StringAttributeFilter sf = (StringAttributeFilter) edgeAttributeFilterString[2];
+                    filter.setEdgeStringAttributeFilter(archetypeIndex, attributeIndex, sf.getFilterValue(), sf.getMatchType());
+                    break;
+                case ENUM:
+                    EnumAttributeFilter ef = (EnumAttributeFilter) edgeAttributeFilterString[2];
+                    filter.setEdgeEnumAttributeFilter(archetypeIndex, attributeIndex, ef.getValueIndices(), ef.getMatchType());
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Creates new string attribute filter with filter value from the json object. and returns it.
+     * @param vertexAttributeFilterInfo - Json object from which to extract the filter value.
+     * @param matchType - Type of matching in the filter.
+     * @return - new String attribute filter object.
+     */
+    private StringAttributeFilter getStringAttributeFilter(JSONObject vertexAttributeFilterInfo, GraphFilter.StringMatchType matchType) {
+        String filterValue = vertexAttributeFilterInfo.getString("value");
+
+        return new StringAttributeFilter(filterValue, matchType);
+    }
+
+    /**
+     * Creates new date attribute filter with filter value from the json object. and returns it.
+     * @param vertexAttributeFilterInfo - Json object from which to extract the filter value.
+     * @param matchType- Type of matching in the filter.
+     * @return - new Date attribute filter object.
+     */
+    private DateAttributeFilter getDateAttributeFilter(JSONObject vertexAttributeFilterInfo, GraphFilter.DateMatchType matchType) {
+        String min = vertexAttributeFilterInfo.getString("min");
+        String max = vertexAttributeFilterInfo.getString("max");
+        boolean minInclusive = vertexAttributeFilterInfo.getBoolean("minInclusive");
+        boolean maxInclusive = vertexAttributeFilterInfo.getBoolean("maxInclusive");
+
+        SimpleDateFormat format = new SimpleDateFormat(GraphJSONDataLoader.DATETIME_FORMAT);
+        Date minDate, maxDate;
+
+        minDate = format.parse(min, new ParsePosition(0));
+        maxDate = format.parse(max, new ParsePosition(0));
+
+        return new DateAttributeFilter(minDate, maxDate, minInclusive, maxInclusive, matchType);
+    }
+
+    /**
+     * Creates new number attribute filter with filter value from the json object. and returns it.
+     * @param vertexAttributeFilterInfo - Json object from which to extract the filter value.
+     * @param matchType - Type of matching in the filter.
+     * @return - new Number attribute filter object.
+     */
+    private NumberAttributeFilter getNumberAttributeFilter(JSONObject vertexAttributeFilterInfo, GraphFilter.NumberMatchType matchType) {
+        BigDecimal min = new BigDecimal(vertexAttributeFilterInfo.getInt("min"));
+        BigDecimal max = new BigDecimal(vertexAttributeFilterInfo.getInt("max"));
+        boolean minInclusive = vertexAttributeFilterInfo.getBoolean("minInclusive");
+        boolean maxInclusive = vertexAttributeFilterInfo.getBoolean("maxInclusive");
+
+        return new NumberAttributeFilter(min, max, minInclusive, maxInclusive, matchType);
+    }
+
+    /**
+     * Loads all the enum values for filtering and returns a list of indexes for those enum values.
+     * @param vertexAttributeName - Name of the vertex attribute for which to get the enum values.
+     * @param vertexAttributeFilterInfo - Json object containing the enum values.
+     * @return Enum attribute filter.
+     */
+    private EnumAttributeFilter getEnumAttributeFilter(String vertexAttributeName, JSONObject vertexAttributeFilterInfo, GraphFilter.EnumMatchType matchType) {
+        List<Integer> valueIndices = new ArrayList<>();
+
+        JSONArray values = vertexAttributeFilterInfo.getJSONArray("values");
+        for (int j = 0; j < values.size(); j++) {
+            String value = values.getString(j);
+            int index = graphManager.getEnumValueIndex(graphManager.getAttributeIndex(vertexAttributeName), value);
+            valueIndices.add(index);
+        }
+
+        return new EnumAttributeFilter(valueIndices, matchType);
+    }
+
+    /**
+     * Loads the archetype icons from the configuration file.
+     * @return -  Map where key is the name of archetype icon and the value is the svg description.
+     */
+    public Map<String, String> loadArchetypeIcons() {
+        Map<String, String> archetypeIcons = new HashMap<>();
+
+        JSONArray archetypeIconsJson = json.getJSONArray("archetypeIcons");
+        for (int i = 0; i < archetypeIconsJson.size(); i++) {
+            JSONObject icon = archetypeIconsJson.getJSONObject(i);
+            String archetypeName = icon.getString("name");
+            String iconSvg = icon.getString("value");
+
+            archetypeIcons.put(archetypeName, iconSvg);
+        }
+
+        return archetypeIcons;
+    }
+
+    /**
+     * Loads default group archetypes.
+     * @return list of indices of archetypes.
+     */
+    public List<Integer> loadGroupArchetypes() {
+        List<Integer> defaultGroupArchetypes = new ArrayList<>();
+
+        JSONArray defaultGroupArchetypesJson = json.getJSONArray("defaultGroupArchetypes");
+        for (int i = 0; i < defaultGroupArchetypesJson.size(); i++) {
+            String archetype = defaultGroupArchetypesJson.get(i).toString();
+            defaultGroupArchetypes.add(graphManager.getVertexArchetypeIndex(archetype));
+        }
+
+        return defaultGroupArchetypes;
+    }
+}
diff --git a/sources/src/cz/zcu/kiv/offscreen/loader/configuration/ConfigurationLoader.java b/sources/src/cz/zcu/kiv/offscreen/loader/configuration/ConfigurationLoader.java
index 95e3d9f..b785824 100644
--- a/sources/src/cz/zcu/kiv/offscreen/loader/configuration/ConfigurationLoader.java
+++ b/sources/src/cz/zcu/kiv/offscreen/loader/configuration/ConfigurationLoader.java
@@ -1,5 +1,7 @@
 package cz.zcu.kiv.offscreen.loader.configuration;
 
+import org.apache.log4j.Logger;
+
 import java.io.IOException;
 import javax.servlet.ServletContext;
 
@@ -10,11 +12,11 @@ import javax.servlet.ServletContext;
 public class ConfigurationLoader {
 
 	public static final String PROP_STORAGE_LOCATION = "storageLocation";
-	public static final String CRCE_API_BASE = "crceApiBase";
+	public static final String PROP_CONFIG_LOCATION = "configLocation";
 
 	/**
 	 * Get storage location property from web.xml.
-	 * 
+	 *
 	 * @param context App context.
 	 * @return Storage location path.
 	 * @throws IOException
@@ -24,13 +26,13 @@ public class ConfigurationLoader {
 	}
 
 	/**
-	 * Get CRCE API base path from web.xml.
+	 * Get configuration location property from web.xml.
 	 *
 	 * @param context App context.
 	 * @return Storage location path.
 	 * @throws IOException
 	 */
-	public static String getCrceApiBase(ServletContext context) throws IOException {
-		return context.getInitParameter(CRCE_API_BASE);
+	public static String getConfigLocation(ServletContext context) throws IOException {
+		return context.getInitParameter(PROP_CONFIG_LOCATION);
 	}
 }
diff --git a/sources/src/cz/zcu/kiv/offscreen/servlets/EfpImport.java b/sources/src/cz/zcu/kiv/offscreen/servlets/EfpImport.java
index f81ae93..91f298f 100644
--- a/sources/src/cz/zcu/kiv/offscreen/servlets/EfpImport.java
+++ b/sources/src/cz/zcu/kiv/offscreen/servlets/EfpImport.java
@@ -1,48 +1,48 @@
-package cz.zcu.kiv.offscreen.servlets;
-
-import java.io.IOException;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-
-import cz.zcu.kiv.offscreen.efp.utils.JsonTransformer;
-
-/**
- * Servlet used for serving JSON data incoming from efpPortal app.
- * 
- * @author Jiri Loudil
- */
-public class EfpImport extends HttpServlet {
-	private static final long serialVersionUID = 1L;
-
-	private Logger logger = Logger.getLogger(LoadGraphData.class);
-
-	@Override
-	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-		String data = request.getParameter("data");
-
-		// invalid data set
-		if (data == null || data.isEmpty()) {
-			logger.error("Data in message are null.");
-			return;
-		}
-
-		JsonTransformer transformer = new JsonTransformer();
-		
-		request.setAttribute("graph_json",true);
-
-		// set the referrer for 'Back' graph button functionality
-		request.setAttribute("efpPortalRefererUrl", request.getHeader("referer"));
-		
-		request.getSession().setAttribute("graph_json_data", transformer.transformInputJSONToGraphJSON(data, request));
-
-		// render
-		RequestDispatcher rd = getServletContext().getRequestDispatcher("/showGraph.jsp");
-		rd.forward(request, response);
-	}
-
-}
+//package cz.zcu.kiv.offscreen.servlets;
+//
+//import java.io.IOException;
+//import javax.servlet.RequestDispatcher;
+//import javax.servlet.ServletException;
+//import javax.servlet.http.HttpServlet;
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//
+//import org.apache.log4j.Logger;
+//
+//import cz.zcu.kiv.offscreen.efp.utils.JsonTransformer;
+//
+///**
+// * Servlet used for serving JSON data incoming from efpPortal app.
+// *
+// * @author Jiri Loudil
+// */
+//public class EfpImport extends HttpServlet {
+//	private static final long serialVersionUID = 1L;
+//
+//	private Logger logger = Logger.getLogger(LoadGraphData.class);
+//
+//	@Override
+//	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+//		String data = request.getParameter("data");
+//
+//		// invalid data set
+//		if (data == null || data.isEmpty()) {
+//			logger.error("Data in message are null.");
+//			return;
+//		}
+//
+//		JsonTransformer transformer = new JsonTransformer();
+//
+//		request.setAttribute("graph_json",true);
+//
+//		// set the referrer for 'Back' graph button functionality
+//		request.setAttribute("efpPortalRefererUrl", request.getHeader("referer"));
+//
+//		request.getSession().setAttribute("graph_json_data", transformer.transformInputJSONToGraphJSON(data, request));
+//
+//		// render
+//		RequestDispatcher rd = getServletContext().getRequestDispatcher("/showGraph.jsp");
+//		rd.forward(request, response);
+//	}
+//
+//}
diff --git a/sources/src/cz/zcu/kiv/offscreen/servlets/LoadGraphData.java b/sources/src/cz/zcu/kiv/offscreen/servlets/LoadGraphData.java
index fc20537..076faa4 100644
--- a/sources/src/cz/zcu/kiv/offscreen/servlets/LoadGraphData.java
+++ b/sources/src/cz/zcu/kiv/offscreen/servlets/LoadGraphData.java
@@ -15,8 +15,11 @@ import cz.zcu.kiv.ccu.ApiInterCompatibilityChecker;
 import cz.zcu.kiv.ccu.ApiInterCompatibilityResult;
 import cz.zcu.kiv.offscreen.api.GraphInterface;
 import cz.zcu.kiv.offscreen.graph.GraphExport;
+import cz.zcu.kiv.offscreen.graph.GraphManager;
 import cz.zcu.kiv.offscreen.graph.creator.GraphMaker;
 import cz.zcu.kiv.offscreen.graph.loader.DemoDiagramLoader;
+import cz.zcu.kiv.offscreen.graph.loader.GraphJSONDataLoader;
+import cz.zcu.kiv.offscreen.graph.loader.JSONConfigLoader;
 import cz.zcu.kiv.offscreen.loader.configuration.ConfigurationLoader;
 import cz.zcu.kiv.offscreen.session.SessionManager;
 import cz.zcu.kiv.offscreen.storage.FileManager;
@@ -50,31 +53,27 @@ public class LoadGraphData extends HttpServlet {
         String storageLocation = ConfigurationLoader.getStorageLocation(request.getServletContext());
 
         FileManager fileManager = new FileManager(workingDirectory, storageLocation);
+        response.setContentType("application/json");
 
         if (request.getSession().getAttribute("demo_id") == null) {
             // it doesn't have EFPs -> read from ComAV
             if (request.getSession().getAttribute("graph_json_data") == null) {
-                // compatibility checking
-                ApiCheckersSetting.Builder settingBuilder = new ApiCheckersSetting.Builder();
-                settingBuilder.defaultSett();
-                ApiCheckersSetting sett = settingBuilder.build();
-                ApiInterCompatibilityChecker<File> checker = ApiCheckersFactory.getApiInterCompatibilityChecker(sett);
-
-                ApiInterCompatibilityResult comparisonResult;
                 File[] uploadedFiles = fileManager.getUploadedComponents().toArray(new File[0]);
-                comparisonResult = checker.checkInterCompatibility(null, uploadedFiles);
-
-                GraphMaker graphMaker = new GraphMaker(storageLocation + File.separator + workingDirectory, comparisonResult, uploadedFiles);
+                File fileToDisplay = uploadedFiles[0];
 
-                GraphInterface graph = graphMaker.generate();
+                GraphManager graphManager = new GraphJSONDataLoader(fileToDisplay).LoadData();
+                String configLocation = ConfigurationLoader.getConfigLocation(request.getServletContext());
+                JSONConfigLoader configLoader = new JSONConfigLoader(graphManager, configLocation);
+                GraphInterface graph = graphManager.createGraph(configLoader);
                 GraphExport export = new GraphExport(graph);
+                JSONObject json = JSONObject.fromObject(export);
+
+                String resultJsonString = json.toString();
 
-                response.setContentType("application/json");
-                response.getWriter().write(JSONObject.fromObject(export).toString());
+                response.getWriter().write(resultJsonString);
 
             } else {
                 // it has EFPs -> read from the session
-                response.setContentType("application/json");
                 response.getWriter().write(request.getSession().getAttribute("graph_json_data").toString());
 
                 request.getSession().removeAttribute("graph_json_data");
@@ -87,7 +86,6 @@ public class LoadGraphData extends HttpServlet {
             DemoDiagramLoader loader = new DemoDiagramLoader();
             InputStream in = this.getServletContext().getResourceAsStream(path);
 
-            response.setContentType("application/json");
             response.getWriter().write(loader.readDemoJSONFromFile(in));
 
             request.getSession().setAttribute("demo_id", null);
diff --git a/sources/src/cz/zcu/kiv/offscreen/servlets/actions/DownloadComponent.java b/sources/src/cz/zcu/kiv/offscreen/servlets/actions/DownloadComponent.java
index b8d884d..1be3897 100644
--- a/sources/src/cz/zcu/kiv/offscreen/servlets/actions/DownloadComponent.java
+++ b/sources/src/cz/zcu/kiv/offscreen/servlets/actions/DownloadComponent.java
@@ -10,6 +10,7 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.log4j.Logger;
 import org.json.JSONObject;
 
 import cz.zcu.kiv.offscreen.loader.configuration.ConfigurationLoader;
@@ -24,52 +25,55 @@ public class DownloadComponent extends HttpServlet {
     private String crceApiBase;
     private FileManager fileManager;
 
+    private Logger logger = Logger.getLogger(DownloadComponent.class);
+
     /**
      * Downloads component by its UUID set in query parameter. The component is then stored in the current graph version
      * folder. As a response, JSON containing component's UUID and filename is returned.
      */
     @Override
     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-        // there was no uuid passed in the request
-        if (request.getParameter("uuid") == null) {
-            response.sendError(response.SC_BAD_REQUEST);
-            return;
-        }
-
-        // initialize file manager
-        String workingDirectory;
-        if (request.getParameter("diagram_hash") == null) {
-            workingDirectory = SessionManager.getSessionValue(request, "JSESSIONID");
-        } else {
-            workingDirectory = request.getParameter("diagram_hash");
-        }
-
-        if (request.getParameter("graphVersion") != null) {
-            workingDirectory += File.separator + request.getParameter("graphVersion");
-        } else {
-            workingDirectory += File.separator + SessionManager.getSessionValue(request, "graphVersion");
-        }
-
-        String storageLocation = ConfigurationLoader.getStorageLocation(request.getServletContext());
-
-        fileManager = new FileManager(workingDirectory, storageLocation);
-        if (!fileManager.isExistStorage()) {
-            fileManager.createStorageDirectory();
-        }
-
-        // download component
-        crceApiBase = ConfigurationLoader.getCrceApiBase(request.getServletContext());
-
-        String uuid = request.getParameter("uuid");
-        String name = downloadComponent(uuid);
-
-        JSONObject componentJson = new JSONObject();
-        componentJson.put("uuid", uuid);
-        componentJson.put("name", name);
-
-        // send response
-        response.setContentType("application/json");
-        response.getWriter().write(componentJson.toString());
+        logger.error("Method is no longer supported because CRCE is removed from project.");
+//        // there was no uuid passed in the request
+//        if (request.getParameter("uuid") == null) {
+//            response.sendError(response.SC_BAD_REQUEST);
+//            return;
+//        }
+//
+//        // initialize file manager
+//        String workingDirectory;
+//        if (request.getParameter("diagram_hash") == null) {
+//            workingDirectory = SessionManager.getSessionValue(request, "JSESSIONID");
+//        } else {
+//            workingDirectory = request.getParameter("diagram_hash");
+//        }
+//
+//        if (request.getParameter("graphVersion") != null) {
+//            workingDirectory += File.separator + request.getParameter("graphVersion");
+//        } else {
+//            workingDirectory += File.separator + SessionManager.getSessionValue(request, "graphVersion");
+//        }
+//
+//        String storageLocation = ConfigurationLoader.getStorageLocation(request.getServletContext());
+//
+//        fileManager = new FileManager(workingDirectory, storageLocation);
+//        if (!fileManager.isExistStorage()) {
+//            fileManager.createStorageDirectory();
+//        }
+//
+//        // download component
+//        crceApiBase = ConfigurationLoader.getCrceApiBase(request.getServletContext());
+//
+//        String uuid = request.getParameter("uuid");
+//        String name = downloadComponent(uuid);
+//
+//        JSONObject componentJson = new JSONObject();
+//        componentJson.put("uuid", uuid);
+//        componentJson.put("name", name);
+//
+//        // send response
+//        response.setContentType("application/json");
+//        response.getWriter().write(componentJson.toString());
     }
 
     /*
diff --git a/sources/src/cz/zcu/kiv/offscreen/storage/FileManager.java b/sources/src/cz/zcu/kiv/offscreen/storage/FileManager.java
index 7047e44..bae9042 100644
--- a/sources/src/cz/zcu/kiv/offscreen/storage/FileManager.java
+++ b/sources/src/cz/zcu/kiv/offscreen/storage/FileManager.java
@@ -20,7 +20,7 @@ public class FileManager {
 
     private int MAX_FILE_SIZE = 512000000;
     private int MAX_MEM_SIZE = 4 * 1024;
-    private static final String ACCEPTED_EXTENSION_FILE = "jar";
+    private static final String ACCEPTED_EXTENSION_FILE = "json";
     private String storagePath;
     private Logger logger = Logger.getLogger(FileManager.class);
 
@@ -43,7 +43,7 @@ public class FileManager {
         return new File(this.storagePath).isDirectory();
     }
 
-    private boolean isJar(String componentName) {
+    private boolean isAcceptedExtension(String componentName) {
         return componentName.endsWith("." + ACCEPTED_EXTENSION_FILE);
     }
 
@@ -64,7 +64,7 @@ public class FileManager {
             List<FileItem> fileItems = upload.parseRequest(request);
             File file;
             for (FileItem fileItem : fileItems) {
-                if (isJar(fileItem.getName()) && fileItem.getSize() > 0) {
+                if (isAcceptedExtension(fileItem.getName()) && fileItem.getSize() > 0) {
                     logger.debug(fileItem.getName() + " - " + fileItem.getContentType());
                     file = new File(this.storagePath + File.separator + fileItem.getName());
                     fileItem.write(file);
@@ -101,7 +101,7 @@ public class FileManager {
     public void saveFile(InputStream inputStream, String fileName) throws IOException {
         File file = new File(this.storagePath + File.separator + fileName);
 
-        if (isJar(file.getName())) {
+        if (isAcceptedExtension(file.getName())) {
             BufferedInputStream in = new BufferedInputStream(inputStream);
             FileOutputStream out = new FileOutputStream(file);
 
