diff --git a/src/main/java/at/ac/uibk/gitsearch/repository/search/MetaDataRepository.java b/src/main/java/at/ac/uibk/gitsearch/repository/search/MetaDataRepository.java
index 85848ab7f0f101b71ec2278d9b278008f8c2abef..1cdf18e3d982e2ace7ec37de1c5d8341c1046185 100644
--- a/src/main/java/at/ac/uibk/gitsearch/repository/search/MetaDataRepository.java
+++ b/src/main/java/at/ac/uibk/gitsearch/repository/search/MetaDataRepository.java
@@ -35,39 +35,12 @@ import at.ac.uibk.gitsearch.config.ApplicationProperties;
 import at.ac.uibk.gitsearch.service.dto.AutoCompleteEntry;
 import at.ac.uibk.gitsearch.service.dto.SearchInputDTO;
 import at.ac.uibk.gitsearch.service.dto.SearchResultsDTO;
-import at.ac.uibk.gitsearch.service.dto.SearchResultsDTO.GitProject;
-import at.ac.uibk.gitsearch.service.dto.SearchResultsDTO.Person;
+import at.ac.uibk.gitsearch.service.dto.UserProvidedMetadataDTO.Person;
 import at.ac.uibk.gitsearch.service.dto.SearchResultDTO;
 
 @Repository
 public class MetaDataRepository {
 
-	/**
-	 * just a local wrapper, to decrypt JSON
-	 *
-	 */
-	public static class SearchResultDTOWrapper {
-        private GitProject project;
-		private SearchResultDTO metadata = new SearchResultDTO();
-
-        public GitProject getProject() {
-            return project;
-        }
-
-        public void setProject(GitProject project) {
-            this.project = project;
-        }
-
-		public SearchResultDTO getMetadata() {
-			return metadata;
-		}
-
-		public void setMetadata(SearchResultDTO metadata) {
-			this.metadata = metadata;
-		}
-
-	}
-
 	private final RestHighLevelClient elasticsearchClient;
 
 	private final ApplicationProperties properties;
@@ -198,7 +171,7 @@ public class MetaDataRepository {
 
 				for (SearchHit searchHit : searchResponse.getHits().getHits()) {
 					final String sourceAsJSON = searchHit.getSourceAsString();
-					SearchResultDTOWrapper entry = objectMapper.readValue(sourceAsJSON, SearchResultDTOWrapper.class);
+					SearchResultDTO entry = objectMapper.readValue(sourceAsJSON, SearchResultDTO.class);
 					if (entry.getMetadata().getKeyword() != null)
 						for (String keyWord : entry.getMetadata().getKeyword())
 							addTo(reloadedCachedCompletions.get(SearchRepositoryConstants.METADATA_KEYWORDS),
@@ -321,10 +294,7 @@ public class MetaDataRepository {
     }
 
     private static SearchResultDTO parseSearchHit(SearchHit searchHit, ObjectMapper objectMapper) throws JsonProcessingException {
-        SearchResultDTOWrapper entry = objectMapper.readValue(searchHit.getSourceAsString(),
-            SearchResultDTOWrapper.class);
-        final SearchResultDTO metadata = entry.getMetadata();
-        return metadata;
+        return objectMapper.readValue(searchHit.getSourceAsString(), SearchResultDTO.class);
     }
 
 	/** Helper **/
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java
index dbac225179dc13f85cd9a94c5530d8bc68803cc4..1b01871e0ad0d61adcf0951480e8704dd5cb3b3b 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java
@@ -7,7 +7,6 @@ import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -136,24 +135,24 @@ public class SearchService {
 	private boolean testAccess(SearchResultDTO p, GitLabApi gitLabApi) {
 		if(true) return true;
 		if(gitLabApi==null) return false;
-					try {
-						Project gitProject = gitLabApi.getProjectApi().getProject(p.getProject().getProject_id());
-						final Permissions permissions = gitProject.getPermissions();
-						log.info("Permissions {}", permissions);
-						boolean access =
-								permissions.getProjectAccess()!=null  &&
-								permissions.getProjectAccess().getAccessLevel().toValue() >= AccessLevel.GUEST.toValue() ||
-								permissions.getGroupAccess() !=null &&
-								permissions.getGroupAccess().getAccessLevel().toValue() >= AccessLevel.GUEST.toValue() ;
-						return access;
-					} catch (GitLabApiException e) {
-						log.debug("It seems that current user cannot access project {}({}) for {}", p.getTitle(), p.getIdentifier(), p.getProject().getProject_id());
-						return false;
-					}
+        try {
+            Project gitProject = gitLabApi.getProjectApi().getProject(p.getProject().getProject_id());
+            final Permissions permissions = gitProject.getPermissions();
+            log.info("Permissions {}", permissions);
+            boolean access =
+                    permissions.getProjectAccess()!=null  &&
+                    permissions.getProjectAccess().getAccessLevel().toValue() >= AccessLevel.GUEST.toValue() ||
+                    permissions.getGroupAccess() !=null &&
+                    permissions.getGroupAccess().getAccessLevel().toValue() >= AccessLevel.GUEST.toValue() ;
+            return access;
+        } catch (GitLabApiException e) {
+            log.debug("It seems that current user cannot access project {}({}) for {}", p.getMetadata().getTitle(), p.getMetadata().getIdentifier(), p.getProject().getProject_id());
+            return false;
+        }
 	}
 
 	private void fixImageURL(SearchResultDTO metaData, GitLabApi gitLabApi) {
-		String image = metaData.getImage();
+		String image = metaData.getMetadata().getImage();
 
 		URI url = null;
 		try {
@@ -162,23 +161,23 @@ public class SearchService {
 
 		final String baseUrl =
 				ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString();
-		final boolean isJava = metaData.getProgrammingLanguage() != null && Arrays.stream(metaData.getProgrammingLanguage()).anyMatch(s -> s.startsWith("JAVA"))
+		final boolean isJava = metaData.getMetadata().getProgrammingLanguage() != null && Arrays.stream(metaData.getMetadata().getProgrammingLanguage()).anyMatch(s -> s.startsWith("JAVA"))
 				&& metaData.hashCode() % 2 == 0; // nur um ein wenig Abwechslung zu bekommen :-)
-		final boolean isLatexFormat = metaData.getFormat()!=null && Arrays.stream(metaData.getFormat()).anyMatch(s -> s.startsWith("latex"));
-		final boolean isPython = metaData.getProgrammingLanguage() != null && Arrays.stream(metaData.getProgrammingLanguage()).anyMatch(s -> s.startsWith("python"));
+		final boolean isLatexFormat = metaData.getMetadata().getFormat()!=null && Arrays.stream(metaData.getMetadata().getFormat()).anyMatch(s -> s.startsWith("latex"));
+		final boolean isPython = metaData.getMetadata().getProgrammingLanguage() != null && Arrays.stream(metaData.getMetadata().getProgrammingLanguage()).anyMatch(s -> s.startsWith("python"));
 		if(isJava) {
-			metaData.setImage(baseUrl + "/content/img/java.png");
+			metaData.getMetadata().setImage(baseUrl + "/content/img/java.png");
 			return;
 		}
 		if(isLatexFormat) {
-			metaData.setImage(baseUrl + "/content/img/latex.png");
+			metaData.getMetadata().setImage(baseUrl + "/content/img/latex.png");
 			return;
 		}
 		if(isPython) {
-			metaData.setImage(baseUrl + "/content/img/python.png");
+			metaData.getMetadata().setImage(baseUrl + "/content/img/python.png");
 			return;
 		}
-		metaData.setImage(baseUrl + "/content/img/gitLab.png");
+		metaData.getMetadata().setImage(baseUrl + "/content/img/gitLab.png");
 		if(true) return;
 
 		if(gitLabApi==null) return;
@@ -188,13 +187,13 @@ public class SearchService {
 			final String httpUrlToRepo = gitProject.getHttpUrlToRepo();
 			String baseRepoURL = httpUrlToRepo.replaceFirst(".git", "/-/raw/master/");
 			final URI resolvedImageUrl = new URI(baseRepoURL).resolve(url);
-			metaData.setImage(resolvedImageUrl.toASCIIString());
+			metaData.getMetadata().setImage(resolvedImageUrl.toASCIIString());
 		} catch (GitLabApiException e) {
-			log.debug("It seems that current user cannot access project {}({}) for {}", metaData.getTitle(), metaData.getIdentifier(), metaData.getProject().getProject_id());
+			log.debug("It seems that current user cannot access project {}({}) for {}", metaData.getMetadata().getTitle(), metaData.getMetadata().getIdentifier(), metaData.getProject().getProject_id());
 		}
 
 		} catch (URISyntaxException e) {
-			log.warn("Cannot parse image url {} for {}", metaData.getImage(), metaData.getGitURL());
+			log.warn("Cannot parse image url {} for {}", metaData.getMetadata().getImage(), metaData.getProject().getUrl());
 		}
 	}
 
@@ -234,7 +233,7 @@ public class SearchService {
                 while (metadataPos < length && metadataPos < loadedMetaData.size()) {
                     final SearchResultDTO loadedMetaDataRecord = new SearchResultDTO(loadedMetaData.get(metadataPos++));
                     if (loadedMetaDataRecord.toString().contains(searchString)) {
-                        loadedMetaDataRecord.setTitle("#" + (recordNr + 1) + " " + loadedMetaDataRecord.getTitle());
+                        loadedMetaDataRecord.getMetadata().setTitle("#" + (recordNr + 1) + " " + loadedMetaDataRecord.getMetadata().getTitle());
                         result.add(loadedMetaDataRecord);
                         recordNr++;
                         log.debug("Added MetaData Record {}", loadedMetaData);
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultDTO.java b/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultDTO.java
index 85383d4ab49eca8d184c79cbe3347fc9db765504..e681ea93e6883a9a24970b28c4472f99da5cf34a 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultDTO.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultDTO.java
@@ -1,398 +1,161 @@
 package at.ac.uibk.gitsearch.service.dto;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-import java.util.Arrays;
 import java.util.Objects;
 
 public class SearchResultDTO {
 
+    private GitProject project;
+    private UserProvidedMetadataDTO metadata;
+
     public SearchResultDTO() {
         // default constructor
     }
 
-    private String metadataVersion; // just for YAML test data reader
-    private String title;
-    private String identifier;
-    private String version;
-    private String structure;
-
-    private String description;
-    private SearchResultsDTO.ExerciseType type;
-    private String license;
-    private String[] keyword;
-
-    private String[] format;
-    private String[] programmingLanguage;
-    private String[] language;
-    private String status;
-
-    private String educationLevel;
-
-    private String gitURL;
-
-    @JsonIgnore
-    private String audience;
-
-    private String timeRequired;
-
-    private SearchResultsDTO.GitProject project;
-
-    @JsonIgnore
-    private String[] collectionContent;
-
-    public String getTimeRequired() {
-        return timeRequired;
-    }
-
-    public void setTimeRequired(String timeRequired) {
-        this.timeRequired = timeRequired;
-    }
-
-    private SearchResultsDTO.Person[] creator;
-    private SearchResultsDTO.Person[] publisher;
-    private SearchResultsDTO.Person[] contributor;
-
-    private boolean deprecated;
-
-    private String difficulty;
-    private String[] source;
-
-    private String[] requires;
-    private String image;
-
-    public String getIdentifier() {
-        return identifier;
-    }
-
-    public void setIdentifier(String identifier) {
-        this.identifier = identifier;
-    }
-
-    public String getVersion() {
-        return version;
-    }
-
-    public void setVersion(String version) {
-        this.version = version;
-    }
-
-    public SearchResultsDTO.ExerciseType getType() {
-        return type;
-    }
-
-    public void setType(SearchResultsDTO.ExerciseType type) {
-        this.type = type;
-    }
-
-    public String[] getLanguage() {
-        return language;
-    }
-
-    public void setLanguage(String[] language) {
-        this.language = language;
-    }
-
-    public String getStatus() {
-        return status;
-    }
-
-    public void setStatus(String status) {
-        this.status = status;
-    }
-
-    public String getEducationLevel() {
-        return educationLevel;
-    }
-
-    public void setEducationLevel(String educationLevel) {
-        this.educationLevel = educationLevel;
-    }
-
-    public String getAudience() {
-        return audience;
-    }
-
-    public void setAudience(String audience) {
-        this.audience = audience;
-    }
-
-    public SearchResultsDTO.Person[] getCreator() {
-        return creator;
-    }
-
-    public void setCreator(SearchResultsDTO.Person[] creator) {
-        this.creator = creator;
-    }
-
-    public SearchResultsDTO.Person[] getPublisher() {
-        return publisher;
-    }
-
-    public void setPublisher(SearchResultsDTO.Person[] publisher) {
-        this.publisher = publisher;
-    }
-
-    public SearchResultsDTO.Person[] getContributor() {
-        return contributor;
-    }
-
-    public void setContributor(SearchResultsDTO.Person[] contributor) {
-        this.contributor = contributor;
-    }
-
-    public boolean isDeprecated() {
-        return deprecated;
-    }
-
-    public void setDeprecated(boolean deprecated) {
-        this.deprecated = deprecated;
-    }
-
-    public String getDifficulty() {
-        return difficulty;
-    }
-
-    public void setDifficulty(String difficulty) {
-        this.difficulty = difficulty;
-    }
-
-    public String[] getSource() {
-        return source;
-    }
-
-    public void setSource(String[] source) {
-        this.source = source;
-    }
-
-    public String[] getRequires() {
-        return requires;
-    }
-
-    public void setRequires(String[] requires) {
-        this.requires = requires;
-    }
-
-    public String getImage() {
-        return image;
-    }
-
-    public void setImage(String image) {
-        this.image = image;
-    }
-
-    private String repositoryURL;
-
-    public String getMetadataVersion() {
-        return metadataVersion;
-    }
-
-    public void setMetadataVersion(String metadataVersion) {
-        this.metadataVersion = metadataVersion;
+    /**
+     * clone constructor
+     *
+     * @param toClone
+     */
+    public SearchResultDTO(SearchResultDTO toClone) {
+        super();
+        this.project = toClone.project;
+        this.metadata = toClone.metadata;
     }
 
-    public String getTitle() {
-        return title;
+    public GitProject getProject() {
+        return project;
     }
 
-    public void setTitle(String title) {
-        this.title = title;
+    public void setProject(GitProject project) {
+        this.project = project;
     }
 
-    public String getDescription() {
-        return description;
+    public UserProvidedMetadataDTO getMetadata() {
+        return metadata;
     }
 
-    public void setDescription(String description) {
-        this.description = description;
+    public void setMetadata(UserProvidedMetadataDTO metadata) {
+        this.metadata = metadata;
     }
 
-    public String getLicense() {
-        return license;
+    @Override
+    public String toString() {
+        return "SearchResultDTO : { project: " + this.project
+            + ", metadata: " + this.metadata
+            + " }";
     }
 
-    public void setLicense(String license) {
-        this.license = license;
+    @Override
+    public int hashCode() {
+        int prime = 31;
+        int result = this.project.hashCode();
+        result = prime * result + this.metadata.hashCode();
+        return result;
     }
 
-    public String[] getKeyword() {
-        return keyword;
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof SearchResultDTO)) {
+            return false;
+        }
+        SearchResultDTO other = (SearchResultDTO) obj;
+        return Objects.equals(this.project, other.project)
+            && Objects.equals(this.metadata, other.metadata);
     }
 
-    public void setKeyword(String[] keyword) {
-        this.keyword = keyword;
-    }
+    public static class GitProject {
+        private int project_id;
+        private String project_name;
+        private String namespace;
+        private String main_group;
+        private String sub_group;
+        private String url;
 
-    public String[] getFormat() {
-        return format;
-    }
+        public int getProject_id() {
+            return project_id;
+        }
 
-    public void setFormat(String[] format) {
-        this.format = format;
-    }
+        public void setProject_id(int project_id) {
+            this.project_id = project_id;
+        }
 
-    public String[] getProgrammingLanguage() {
-        return programmingLanguage;
-    }
+        public String getProject_name() {
+            return project_name;
+        }
 
-    public void setProgrammingLanguage(String[] programmingLanguage) {
-        this.programmingLanguage = programmingLanguage;
-    }
+        public void setProject_name(String project_name) {
+            this.project_name = project_name;
+        }
 
-    public String getRepositoryURL() {
-        return repositoryURL;
-    }
+        public String getNamespace() {
+            return namespace;
+        }
 
-    public void setRepositoryURL(String repositoryURL) {
-        this.repositoryURL = repositoryURL;
-    }
+        public void setNamespace(String namespace) {
+            this.namespace = namespace;
+        }
 
-    public String getStructure() {
-        return structure;
-    }
+        public String getMain_group() {
+            return main_group;
+        }
 
-    public void setStructure(String structure) {
-        this.structure = structure;
-    }
+        public void setMain_group(String main_group) {
+            this.main_group = main_group;
+        }
 
-    public String getGitURL() {
-        return gitURL;
-    }
+        public String getSub_group() {
+            return sub_group;
+        }
 
-    public void setGitURL(String gitURL) {
-        this.gitURL = gitURL;
-    }
+        public void setSub_group(String sub_group) {
+            this.sub_group = sub_group;
+        }
 
-    public SearchResultsDTO.GitProject getProject() {
-        return project;
-    }
+        public String getUrl() {
+            return url;
+        }
 
-    public void setProject(SearchResultsDTO.GitProject project) {
-        this.project = project;
-    }
+        public void setUrl(String url) {
+            this.url = url;
+        }
 
-    /**
-     * clone constructor
-     *
-     * @param toClone
-     */
-    public SearchResultDTO(SearchResultDTO toClone) {
-        super();
-        this.metadataVersion = toClone.metadataVersion;
-        this.title = toClone.title;
-        this.identifier = toClone.identifier;
-        this.version = toClone.version;
-        this.structure = toClone.structure;
-        this.description = toClone.description;
-        this.type = toClone.type;
-        this.license = toClone.license;
-        this.keyword = toClone.keyword;
-        this.format = toClone.format;
-        this.programmingLanguage = toClone.programmingLanguage;
-        this.language = toClone.language;
-        this.status = toClone.status;
-        this.educationLevel = toClone.educationLevel;
-        this.gitURL = toClone.gitURL;
-        this.audience = toClone.audience;
-        this.timeRequired = toClone.timeRequired;
-        this.collectionContent = toClone.collectionContent;
-        this.creator = toClone.creator;
-        this.publisher = toClone.publisher;
-        this.contributor = toClone.contributor;
-        this.deprecated = toClone.deprecated;
-        this.difficulty = toClone.difficulty;
-        this.source = toClone.source;
-        this.requires = toClone.requires;
-        this.image = toClone.image;
-        this.repositoryURL = toClone.repositoryURL;
-    }
+        public int getProjectId() {
+            return project_id;
+        }
 
-    @Override
-    public String toString() {
-        return "SearchResultDTO [audience=" + audience + ", collectionContent=" + Arrays.toString(collectionContent)
-            + ", contributor=" + Arrays.toString(contributor) + ", creator=" + Arrays.toString(creator)
-            + ", deprecated=" + deprecated + ", description=" + description + ", difficulty=" + difficulty
-            + ", educationLevel=" + educationLevel + ", format=" + Arrays.toString(format) + ", gitURL=" + gitURL
-            + ", identifier=" + identifier + ", image=" + image + ", keyword=" + Arrays.toString(keyword)
-            + ", language=" + Arrays.toString(language) + ", license=" + license + ", metadataVersion="
-            + metadataVersion + ", programmingLanguage=" + Arrays.toString(programmingLanguage) + ", publisher="
-            + Arrays.toString(publisher) + ", repositoryURL=" + repositoryURL + ", requires=" + Arrays.toString(requires)
-            + ", source=" + Arrays.toString(source) + ", status=" + status + ", structure=" + structure
-            + ", timeRequired=" + timeRequired + ", title=" + title + ", type=" + type + ", version=" + version
-            + "]";
-    }
+        public void setProjectId(int project_id) {
+            this.project_id = project_id;
+        }
 
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((audience == null) ? 0 : audience.hashCode());
-        result = prime * result + Arrays.hashCode(collectionContent);
-        result = prime * result + Arrays.hashCode(contributor);
-        result = prime * result + Arrays.hashCode(creator);
-        result = prime * result + (deprecated ? 1231 : 1237);
-        result = prime * result + ((description == null) ? 0 : description.hashCode());
-        result = prime * result + ((difficulty == null) ? 0 : difficulty.hashCode());
-        result = prime * result + ((educationLevel == null) ? 0 : educationLevel.hashCode());
-        result = prime * result + Arrays.hashCode(format);
-        result = prime * result + ((gitURL == null) ? 0 : gitURL.hashCode());
-        result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
-        result = prime * result + ((image == null) ? 0 : image.hashCode());
-        result = prime * result + Arrays.hashCode(keyword);
-        result = prime * result + Arrays.hashCode(language);
-        result = prime * result + ((license == null) ? 0 : license.hashCode());
-        result = prime * result + ((metadataVersion == null) ? 0 : metadataVersion.hashCode());
-        result = prime * result + Arrays.hashCode(programmingLanguage);
-        result = prime * result + ((project == null) ? 0 : project.hashCode());
-        result = prime * result + Arrays.hashCode(publisher);
-        result = prime * result + ((repositoryURL == null) ? 0 : repositoryURL.hashCode());
-        result = prime * result + Arrays.hashCode(requires);
-        result = prime * result + Arrays.hashCode(source);
-        result = prime * result + ((status == null) ? 0 : status.hashCode());
-        result = prime * result + ((structure == null) ? 0 : structure.hashCode());
-        result = prime * result + ((timeRequired == null) ? 0 : timeRequired.hashCode());
-        result = prime * result + ((title == null) ? 0 : title.hashCode());
-        result = prime * result + ((type == null) ? 0 : type.hashCode());
-        result = prime * result + ((version == null) ? 0 : version.hashCode());
-        return result;
-    }
+        @Override
+        public int hashCode() {
+            return Integer.hashCode(project_id);
+        }
 
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof GitProject)) {
+                return false;
+            }
+            GitProject other = (GitProject) obj;
+            return this.project_id == other.project_id;
         }
-        if (!(obj instanceof SearchResultDTO)) {
-            return false;
+
+        @Override
+        public String toString() {
+            return  "Project: { project_id: " + project_id
+                + ", project_name: " + project_name
+                + ", namespace: " + namespace
+                + ", main_group: " + main_group
+                + ", sub_group: " + sub_group
+                + ", url: " + url
+                + " }";
         }
-        SearchResultDTO other = (SearchResultDTO) obj;
-        return Objects.equals(this.audience, other.audience)
-            && Arrays.equals(this.collectionContent, other.collectionContent)
-            && Arrays.equals(this.contributor, other.contributor)
-            && Arrays.equals(this.creator, other.creator)
-            && this.deprecated == other.deprecated
-            && Objects.equals(this.description, other.description)
-            && Objects.equals(this.difficulty, other.difficulty)
-            && Objects.equals(this.educationLevel, other.educationLevel)
-            && Arrays.equals(this.format, other.format)
-            && Objects.equals(this.gitURL, other.gitURL)
-            && Objects.equals(this.identifier, other.identifier)
-            && Objects.equals(this.image, other.image)
-            && Arrays.equals(this.keyword, other.keyword)
-            && Arrays.equals(this.language, other.language)
-            && Objects.equals(this.license, other.license)
-            && Objects.equals(this.metadataVersion, other.metadataVersion)
-            && Arrays.equals(this.programmingLanguage, other.programmingLanguage)
-            && Objects.equals(this.project, other.project)
-            && Arrays.equals(this.publisher, other.publisher)
-            && Objects.equals(this.repositoryURL, other.repositoryURL)
-            && Arrays.equals(this.requires, other.requires)
-            && Arrays.equals(this.source, other.source)
-            && Objects.equals(this.status, other.status)
-            && Objects.equals(this.structure, other.structure)
-            && Objects.equals(this.timeRequired, other.timeRequired)
-            && Objects.equals(this.title, other.title)
-            && this.type == other.type
-            && Objects.equals(this.version, other.version);
     }
 }
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java b/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java
index 121490daf2efb2c71b5f48a8fe04a1284b531740..9fd9000b2e41d89926dff04df4a6d44939f8505e 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java
@@ -1,182 +1,9 @@
 package at.ac.uibk.gitsearch.service.dto;
 
 import java.util.List;
-import java.util.Objects;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonValue;
 
 public class SearchResultsDTO {
 
-	@JsonFormat(shape = JsonFormat.Shape.OBJECT)
-	public enum ExerciseType {
-		PROGRAMMING_EXERCISE("programming exercise"), EXERCISE("exercise"), COLLECTION("collection"), OTHER("other");
-
-		ExerciseType(String externalName) {
-			this.externalName = externalName;
-		}
-
-		private final String externalName;
-
-		@JsonValue
-		public String getExternalName() {
-			return externalName;
-		}
-	}
-
-	public static class Person {
-		private String name;
-		private String affiliation;
-		private String email;
-
-		public String getName() {
-			return name;
-		}
-
-		public void setName(String name) {
-			this.name = name;
-		}
-
-		public String getAffiliation() {
-			return affiliation;
-		}
-
-		public void setAffiliation(String affiliation) {
-			this.affiliation = affiliation;
-		}
-
-		public String getEmail() {
-			return email;
-		}
-
-		public void setEmail(String email) {
-			this.email = email;
-		}
-
-		@Override
-		public String toString() {
-			return "Person: { name: " + this.name + ", affiliation: " + this.affiliation + ", email: " + this.email
-					+ "}";
-		}
-
-		@Override
-		public int hashCode() {
-			final int prime = 31;
-			int result = 1;
-			result = prime * result + ((affiliation == null) ? 0 : affiliation.hashCode());
-			result = prime * result + ((email == null) ? 0 : email.hashCode());
-			result = prime * result + ((name == null) ? 0 : name.hashCode());
-			return result;
-		}
-
-		@Override
-		public boolean equals(Object obj) {
-			if (this == obj) {
-                return true;
-            }
-			if (!(obj instanceof Person)) {
-			    return false;
-            }
-			Person other = (Person) obj;
-			return Objects.equals(this.affiliation, other.affiliation)
-                && Objects.equals(this.email, other.email)
-                && Objects.equals(this.name, other.name);
-		}
-	}
-
-	public static class GitProject {
-		private int project_id;
-		private String project_name;
-		private String namespace;
-		private String main_group;
-		private String sub_group;
-		private String url;
-
-		public int getProject_id() {
-			return project_id;
-		}
-
-		public void setProject_id(int project_id) {
-			this.project_id = project_id;
-		}
-
-        public String getProject_name() {
-            return project_name;
-        }
-
-        public void setProject_name(String project_name) {
-            this.project_name = project_name;
-        }
-
-        public String getNamespace() {
-            return namespace;
-        }
-
-        public void setNamespace(String namespace) {
-            this.namespace = namespace;
-        }
-
-        public String getMain_group() {
-            return main_group;
-        }
-
-        public void setMain_group(String main_group) {
-            this.main_group = main_group;
-        }
-
-        public String getSub_group() {
-            return sub_group;
-        }
-
-        public void setSub_group(String sub_group) {
-            this.sub_group = sub_group;
-        }
-
-        public String getUrl() {
-            return url;
-        }
-
-        public void setUrl(String url) {
-            this.url = url;
-        }
-
-        public int getProjectId() {
-			return project_id;
-		}
-
-		public void setProjectId(int project_id) {
-			this.project_id = project_id;
-		}
-
-		@Override
-		public int hashCode() {
-		    return Integer.hashCode(project_id);
-		}
-
-		@Override
-		public boolean equals(Object obj) {
-			if (this == obj) {
-                return true;
-            }
-			if (!(obj instanceof GitProject)) {
-			    return false;
-            }
-			GitProject other = (GitProject) obj;
-			return this.project_id == other.project_id;
-		}
-
-        @Override
-        public String toString() {
-            return  "Project: { project_id: " + project_id
-                + ", project_name: " + project_name
-                + ", namespace: " + namespace
-                + ", main_group: " + main_group
-                + ", sub_group: " + sub_group
-                + ", url: " + url
-                + " }";
-        }
-    }
-
 	private List<SearchResultDTO> searchResult;
 
 	/**
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/dto/UserProvidedMetadataDTO.java b/src/main/java/at/ac/uibk/gitsearch/service/dto/UserProvidedMetadataDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0ca107c2c98beb79d887642e9b96263b932f4ef
--- /dev/null
+++ b/src/main/java/at/ac/uibk/gitsearch/service/dto/UserProvidedMetadataDTO.java
@@ -0,0 +1,471 @@
+package at.ac.uibk.gitsearch.service.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+public class UserProvidedMetadataDTO {
+
+    public UserProvidedMetadataDTO() {
+        // default constructor
+    }
+
+    private String metadataVersion; // just for YAML test data reader
+    private String title;
+    private String identifier;
+    private String version;
+    private String structure;
+
+    private String description;
+    private ExerciseType type;
+    private String license;
+    private String[] keyword;
+
+    private String[] format;
+    private String[] programmingLanguage;
+    private String[] language;
+    private String status;
+
+    private String educationLevel;
+
+    @JsonIgnore
+    private String audience;
+
+    private String timeRequired;
+
+    @JsonIgnore
+    private String[] collectionContent;
+
+    private Person[] creator;
+    private Person[] publisher;
+    private Person[] contributor;
+
+    private boolean deprecated;
+
+    private String difficulty;
+    private String[] source;
+
+    private String[] requires;
+    private String image;
+
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    public void setIdentifier(String identifier) {
+        this.identifier = identifier;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public ExerciseType getType() {
+        return type;
+    }
+
+    public void setType(ExerciseType type) {
+        this.type = type;
+    }
+
+    public String[] getLanguage() {
+        return language;
+    }
+
+    public void setLanguage(String[] language) {
+        this.language = language;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getEducationLevel() {
+        return educationLevel;
+    }
+
+    public void setEducationLevel(String educationLevel) {
+        this.educationLevel = educationLevel;
+    }
+
+    public String getAudience() {
+        return audience;
+    }
+
+    public void setAudience(String audience) {
+        this.audience = audience;
+    }
+
+    public String getTimeRequired() {
+        return timeRequired;
+    }
+
+    public void setTimeRequired(String timeRequired) {
+        this.timeRequired = timeRequired;
+    }
+
+    public Person[] getCreator() {
+        return creator;
+    }
+
+    public void setCreator(Person[] creator) {
+        this.creator = creator;
+    }
+
+    public Person[] getPublisher() {
+        return publisher;
+    }
+
+    public void setPublisher(Person[] publisher) {
+        this.publisher = publisher;
+    }
+
+    public Person[] getContributor() {
+        return contributor;
+    }
+
+    public void setContributor(Person[] contributor) {
+        this.contributor = contributor;
+    }
+
+    public boolean isDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(boolean deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public String getDifficulty() {
+        return difficulty;
+    }
+
+    public void setDifficulty(String difficulty) {
+        this.difficulty = difficulty;
+    }
+
+    public String[] getSource() {
+        return source;
+    }
+
+    public void setSource(String[] source) {
+        this.source = source;
+    }
+
+    public String[] getRequires() {
+        return requires;
+    }
+
+    public void setRequires(String[] requires) {
+        this.requires = requires;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    private String repositoryURL;
+
+    public String getMetadataVersion() {
+        return metadataVersion;
+    }
+
+    public void setMetadataVersion(String metadataVersion) {
+        this.metadataVersion = metadataVersion;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getLicense() {
+        return license;
+    }
+
+    public void setLicense(String license) {
+        this.license = license;
+    }
+
+    public String[] getKeyword() {
+        return keyword;
+    }
+
+    public void setKeyword(String[] keyword) {
+        this.keyword = keyword;
+    }
+
+    public String[] getFormat() {
+        return format;
+    }
+
+    public void setFormat(String[] format) {
+        this.format = format;
+    }
+
+    public String[] getProgrammingLanguage() {
+        return programmingLanguage;
+    }
+
+    public void setProgrammingLanguage(String[] programmingLanguage) {
+        this.programmingLanguage = programmingLanguage;
+    }
+
+    public String getRepositoryURL() {
+        return repositoryURL;
+    }
+
+    public void setRepositoryURL(String repositoryURL) {
+        this.repositoryURL = repositoryURL;
+    }
+
+    public String getStructure() {
+        return structure;
+    }
+
+    public void setStructure(String structure) {
+        this.structure = structure;
+    }
+
+    /**
+     * clone constructor
+     *
+     * @param toClone
+     */
+    public UserProvidedMetadataDTO(UserProvidedMetadataDTO toClone) {
+        super();
+        this.metadataVersion = toClone.metadataVersion;
+        this.title = toClone.title;
+        this.identifier = toClone.identifier;
+        this.version = toClone.version;
+        this.structure = toClone.structure;
+        this.description = toClone.description;
+        this.type = toClone.type;
+        this.license = toClone.license;
+        this.keyword = toClone.keyword;
+        this.format = toClone.format;
+        this.programmingLanguage = toClone.programmingLanguage;
+        this.language = toClone.language;
+        this.status = toClone.status;
+        this.educationLevel = toClone.educationLevel;
+        this.audience = toClone.audience;
+        this.timeRequired = toClone.timeRequired;
+        this.collectionContent = toClone.collectionContent;
+        this.creator = toClone.creator;
+        this.publisher = toClone.publisher;
+        this.contributor = toClone.contributor;
+        this.deprecated = toClone.deprecated;
+        this.difficulty = toClone.difficulty;
+        this.source = toClone.source;
+        this.requires = toClone.requires;
+        this.image = toClone.image;
+        this.repositoryURL = toClone.repositoryURL;
+    }
+
+    @Override
+    public String toString() {
+        return "UserProvidedMetadataDTO { audience: " + audience
+            + ", collectionContent: " + Arrays.toString(collectionContent)
+            + ", contributor: " + Arrays.toString(contributor)
+            + ", creator: " + Arrays.toString(creator)
+            + ", deprecated: " + deprecated
+            + ", description: " + description
+            + ", difficulty: " + difficulty
+            + ", educationLevel: " + educationLevel
+            + ", format: " + Arrays.toString(format)
+            + ", identifier:" + identifier
+            + ", image: " + image
+            + ", keyword: " + Arrays.toString(keyword)
+            + ", language: " + Arrays.toString(language)
+            + ", license: " + license
+            + ", metadataVersion: " + metadataVersion
+            + ", programmingLanguage: " + Arrays.toString(programmingLanguage)
+            + ", publisher: " + Arrays.toString(publisher)
+            + ", repositoryURL: " + repositoryURL
+            + ", requires: " + Arrays.toString(requires)
+            + ", source: " + Arrays.toString(source)
+            + ", status: " + status
+            + ", structure: " + structure
+            + ", timeRequired: " + timeRequired
+            + ", title: " + title
+            + ", type: " + type
+            + ", version: " + version
+            + " }";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((audience == null) ? 0 : audience.hashCode());
+        result = prime * result + Arrays.hashCode(collectionContent);
+        result = prime * result + Arrays.hashCode(contributor);
+        result = prime * result + Arrays.hashCode(creator);
+        result = prime * result + (deprecated ? 1231 : 1237);
+        result = prime * result + ((description == null) ? 0 : description.hashCode());
+        result = prime * result + ((difficulty == null) ? 0 : difficulty.hashCode());
+        result = prime * result + ((educationLevel == null) ? 0 : educationLevel.hashCode());
+        result = prime * result + Arrays.hashCode(format);
+        result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
+        result = prime * result + ((image == null) ? 0 : image.hashCode());
+        result = prime * result + Arrays.hashCode(keyword);
+        result = prime * result + Arrays.hashCode(language);
+        result = prime * result + ((license == null) ? 0 : license.hashCode());
+        result = prime * result + ((metadataVersion == null) ? 0 : metadataVersion.hashCode());
+        result = prime * result + Arrays.hashCode(programmingLanguage);
+        result = prime * result + Arrays.hashCode(publisher);
+        result = prime * result + ((repositoryURL == null) ? 0 : repositoryURL.hashCode());
+        result = prime * result + Arrays.hashCode(requires);
+        result = prime * result + Arrays.hashCode(source);
+        result = prime * result + ((status == null) ? 0 : status.hashCode());
+        result = prime * result + ((structure == null) ? 0 : structure.hashCode());
+        result = prime * result + ((timeRequired == null) ? 0 : timeRequired.hashCode());
+        result = prime * result + ((title == null) ? 0 : title.hashCode());
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        result = prime * result + ((version == null) ? 0 : version.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof UserProvidedMetadataDTO)) {
+            return false;
+        }
+        UserProvidedMetadataDTO other = (UserProvidedMetadataDTO) obj;
+        return Objects.equals(this.audience, other.audience)
+            && Arrays.equals(this.collectionContent, other.collectionContent)
+            && Arrays.equals(this.contributor, other.contributor)
+            && Arrays.equals(this.creator, other.creator)
+            && this.deprecated == other.deprecated
+            && Objects.equals(this.description, other.description)
+            && Objects.equals(this.difficulty, other.difficulty)
+            && Objects.equals(this.educationLevel, other.educationLevel)
+            && Arrays.equals(this.format, other.format)
+            && Objects.equals(this.identifier, other.identifier)
+            && Objects.equals(this.image, other.image)
+            && Arrays.equals(this.keyword, other.keyword)
+            && Arrays.equals(this.language, other.language)
+            && Objects.equals(this.license, other.license)
+            && Objects.equals(this.metadataVersion, other.metadataVersion)
+            && Arrays.equals(this.programmingLanguage, other.programmingLanguage)
+            && Arrays.equals(this.publisher, other.publisher)
+            && Objects.equals(this.repositoryURL, other.repositoryURL)
+            && Arrays.equals(this.requires, other.requires)
+            && Arrays.equals(this.source, other.source)
+            && Objects.equals(this.status, other.status)
+            && Objects.equals(this.structure, other.structure)
+            && Objects.equals(this.timeRequired, other.timeRequired)
+            && Objects.equals(this.title, other.title)
+            && this.type == other.type
+            && Objects.equals(this.version, other.version);
+    }
+
+
+    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
+    public enum ExerciseType {
+        PROGRAMMING_EXERCISE("programming exercise"), EXERCISE("exercise"), COLLECTION("collection"), OTHER("other");
+
+        ExerciseType(String externalName) {
+            this.externalName = externalName;
+        }
+
+        private final String externalName;
+
+        @JsonValue
+        public String getExternalName() {
+            return externalName;
+        }
+    }
+
+    public static class Person {
+        private String name;
+        private String affiliation;
+        private String email;
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getAffiliation() {
+            return affiliation;
+        }
+
+        public void setAffiliation(String affiliation) {
+            this.affiliation = affiliation;
+        }
+
+        public String getEmail() {
+            return email;
+        }
+
+        public void setEmail(String email) {
+            this.email = email;
+        }
+
+        @Override
+        public String toString() {
+            return "Person: { name: " + this.name
+                + ", affiliation: " + this.affiliation
+                + ", email: " + this.email
+                + " }";
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((affiliation == null) ? 0 : affiliation.hashCode());
+            result = prime * result + ((email == null) ? 0 : email.hashCode());
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof Person)) {
+                return false;
+            }
+            Person other = (Person) obj;
+            return Objects.equals(this.affiliation, other.affiliation)
+                && Objects.equals(this.email, other.email)
+                && Objects.equals(this.name, other.name);
+        }
+    }
+}
+