diff --git a/src/main/java/cz/cvut/kbss/study/model/Role.java b/src/main/java/cz/cvut/kbss/study/model/Role.java
new file mode 100644
index 00000000..8303c4ff
--- /dev/null
+++ b/src/main/java/cz/cvut/kbss/study/model/Role.java
@@ -0,0 +1,109 @@
+package cz.cvut.kbss.study.model;
+
+import cz.cvut.kbss.jopa.model.annotations.Individual;
+
+public enum Role {
+
+ // TODO deprecated -- should be removed.
+ @Individual(iri=Vocabulary.s_i_administrator)
+ administrator(Vocabulary.s_i_administrator),
+ // TODO deprecated -- should be removed.
+ @Individual(iri = Vocabulary.s_i_user)
+ user(Vocabulary.s_i_user),
+
+ @Individual(iri = Vocabulary.s_i_impersonate_role)
+ impersonate(Vocabulary.s_i_impersonate_role),
+
+ @Individual(iri = Vocabulary.s_i_delete_all_records_role)
+ deleteAllRecords(Vocabulary.s_i_delete_all_records_role),
+
+ @Individual(iri = Vocabulary.s_i_view_all_records_role)
+ viewAllRecords(Vocabulary.s_i_view_all_records_role),
+
+ @Individual(iri = Vocabulary.s_i_edit_all_records_role)
+ editAllRecords(Vocabulary.s_i_edit_all_records_role),
+
+ @Individual(iri = Vocabulary.s_i_delete_organization_records_role)
+ deleteOrganizationRecords(Vocabulary.s_i_delete_organization_records_role),
+
+ @Individual(iri = Vocabulary.s_i_view_organization_records_role)
+ viewOrganizationRecords(Vocabulary.s_i_view_organization_records_role),
+
+ @Individual(iri = Vocabulary.s_i_edit_organization_records_role)
+ editOrganizationRecords(Vocabulary.s_i_edit_organization_records_role),
+
+ @Individual(iri = Vocabulary.s_i_edit_users_role)
+ editUsers(Vocabulary.s_i_edit_users_role),
+
+ @Individual(iri = Vocabulary.s_i_complete_records_role)
+ completeRecords(Vocabulary.s_i_complete_records_role),
+
+ @Individual(iri = Vocabulary.s_i_reject_records_role)
+ rejectRecords(Vocabulary.s_i_reject_records_role),
+
+ @Individual(iri = Vocabulary.s_i_publish_records_role)
+ publishRecords(Vocabulary.s_i_publish_records_role),
+
+ @Individual(iri = Vocabulary.s_i_import_codelists_role)
+ importCodelists(Vocabulary.s_i_import_codelists_role);
+
+ private final String iri;
+
+ Role(String iri) {
+ this.iri = iri;
+ }
+
+ public String getIri() {
+ return iri;
+ }
+
+ /**
+ * Returns {@link Role} with the specified IRI.
+ *
+ * @param iri role identifier
+ * @return matching {@code Role}
+ * @throws IllegalArgumentException When no matching role is found
+ */
+ public static Role fromIri(String iri) {
+ for (Role r : values()) {
+ if (r.getIri().equals(iri)) {
+ return r;
+ }
+ }
+ throw new IllegalArgumentException("Unknown role identifier '" + iri + "'.");
+ }
+
+ /**
+ * Returns {@link Role} with the specified constant name.
+ *
+ * @param name role name
+ * @return matching {@code Role}
+ * @throws IllegalArgumentException When no matching role is found
+ */
+ public static Role fromName(String name) {
+ for (Role r : values()) {
+ if (r.name().equalsIgnoreCase(name)) {
+ return r;
+ }
+ }
+ throw new IllegalArgumentException("Unknown role '" + name + "'.");
+ }
+
+ /**
+ * Returns a {@link Role} with the specified IRI or constant name.
+ *
+ * This function first tries to find the enum constant by IRI. If it is not found, constant name matching is
+ * attempted.
+ *
+ * @param identification Constant IRI or name to find match by
+ * @return matching {@code Role}
+ * @throws IllegalArgumentException When no matching role is found
+ */
+ public static Role fromIriOrName(String identification) {
+ try {
+ return fromIri(identification);
+ } catch (IllegalArgumentException e) {
+ return fromName(identification);
+ }
+ }
+}
diff --git a/src/main/java/cz/cvut/kbss/study/model/RoleGroup.java b/src/main/java/cz/cvut/kbss/study/model/RoleGroup.java
new file mode 100644
index 00000000..c687f78a
--- /dev/null
+++ b/src/main/java/cz/cvut/kbss/study/model/RoleGroup.java
@@ -0,0 +1,59 @@
+package cz.cvut.kbss.study.model;
+import cz.cvut.kbss.jopa.model.annotations.*;
+import cz.cvut.kbss.study.model.util.HasDerivableUri;
+import cz.cvut.kbss.study.model.util.HasOwlKey;
+import cz.cvut.kbss.study.util.Constants;
+
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+@OWLClass(iri = Vocabulary.s_c_role_group)
+public class RoleGroup implements HasDerivableUri {
+
+ @Id
+ private URI uri;
+
+ @OWLAnnotationProperty(iri = Vocabulary.s_p_label)
+ private String name;
+
+ @OWLObjectProperty(iri = Vocabulary.s_p_has_role)
+ private Set roles;
+
+ public void addRole(Role role){
+ if(roles == null){
+ roles = new HashSet<>();
+ }
+ roles.add(role);
+ }
+
+
+ public URI getUri() {
+ return uri;
+ }
+
+ public void setUri(URI uri) {
+ this.uri = uri;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Set getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set roles) {
+ this.roles = roles;
+ }
+
+ @Override
+ public void generateUri() {
+ this.uri = URI.create(Constants.BASE_URI + name);
+ }
+}
diff --git a/src/main/java/cz/cvut/kbss/study/persistence/dao/RoleGroupDao.java b/src/main/java/cz/cvut/kbss/study/persistence/dao/RoleGroupDao.java
new file mode 100644
index 00000000..c78dfb5b
--- /dev/null
+++ b/src/main/java/cz/cvut/kbss/study/persistence/dao/RoleGroupDao.java
@@ -0,0 +1,31 @@
+package cz.cvut.kbss.study.persistence.dao;
+
+import cz.cvut.kbss.jopa.exceptions.NoResultException;
+import cz.cvut.kbss.jopa.model.EntityManager;
+import cz.cvut.kbss.study.model.RoleGroup;
+import cz.cvut.kbss.study.util.Constants;
+import org.springframework.stereotype.Repository;
+import java.net.URI;
+import cz.cvut.kbss.study.model.Vocabulary;
+
+@Repository
+public class RoleGroupDao extends DerivableUriDao {
+
+ protected RoleGroupDao(EntityManager em) {
+ super(RoleGroup.class, em);
+ }
+
+ public RoleGroup findByName(String name) {
+ if (name == null) {
+ return null;
+ }
+ try {
+ return em.createNativeQuery("SELECT ?x WHERE { ?x ?hasName ?name . }", RoleGroup.class)
+ .setParameter("hasName", URI.create(Vocabulary.s_p_label))
+ .setParameter("name", name, Constants.PU_LANGUAGE).getSingleResult();
+ } catch (NoResultException e) {
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/cz/cvut/kbss/study/service/RoleGroupService.java b/src/main/java/cz/cvut/kbss/study/service/RoleGroupService.java
new file mode 100644
index 00000000..554b21be
--- /dev/null
+++ b/src/main/java/cz/cvut/kbss/study/service/RoleGroupService.java
@@ -0,0 +1,8 @@
+package cz.cvut.kbss.study.service;
+
+import cz.cvut.kbss.study.model.RoleGroup;
+import org.springframework.stereotype.Service;
+
+public interface RoleGroupService {
+ RoleGroup findByName(String name);
+}
diff --git a/src/main/java/cz/cvut/kbss/study/service/repository/RepositoryRoleGroup.java b/src/main/java/cz/cvut/kbss/study/service/repository/RepositoryRoleGroup.java
new file mode 100644
index 00000000..b6cb5d75
--- /dev/null
+++ b/src/main/java/cz/cvut/kbss/study/service/repository/RepositoryRoleGroup.java
@@ -0,0 +1,21 @@
+package cz.cvut.kbss.study.service.repository;
+
+import cz.cvut.kbss.study.model.RoleGroup;
+import cz.cvut.kbss.study.persistence.dao.RoleGroupDao;
+import cz.cvut.kbss.study.service.RoleGroupService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class RepositoryRoleGroup implements RoleGroupService {
+
+ private final RoleGroupDao roleGroupDao;
+
+ public RepositoryRoleGroup(RoleGroupDao roleGroupDao) {
+ this.roleGroupDao = roleGroupDao;
+ }
+
+ @Override
+ public RoleGroup findByName(String name) {
+ return roleGroupDao.findByName(name);
+ }
+}
diff --git a/src/test/java/cz/cvut/kbss/study/model/RoleTest.java b/src/test/java/cz/cvut/kbss/study/model/RoleTest.java
new file mode 100644
index 00000000..8f7209dc
--- /dev/null
+++ b/src/test/java/cz/cvut/kbss/study/model/RoleTest.java
@@ -0,0 +1,71 @@
+package cz.cvut.kbss.study.model;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+class RoleTest {
+
+ @Test
+ void fromIriReturnsCorrectRole() {
+ assertEquals(Role.administrator, Role.fromIri(Vocabulary.s_i_administrator));
+ assertEquals(Role.viewAllRecords, Role.fromIri(Vocabulary.s_i_view_all_records_role));
+ }
+
+ @Test
+ void fromIriThrowsExceptionForUnknownIri() {
+ String unknownIri = "unknown_iri";
+ Exception exception = assertThrows(IllegalArgumentException.class, () -> {
+ Role.fromIri(unknownIri);
+ });
+ assertEquals("Unknown role identifier '" + unknownIri + "'.", exception.getMessage());
+ }
+
+
+ @Test
+ void fromNameReturnsCorrectRole() {
+ assertEquals(Role.administrator, Role.fromName("administrator"));
+ assertEquals(Role.viewAllRecords, Role.fromName("viewAllRecords"));
+ }
+
+ @Test
+ void fromNameIsCaseInsensitive() {
+ assertEquals(Role.administrator, Role.fromName("ADMINISTRATOR"));
+ assertEquals(Role.viewAllRecords, Role.fromName("VIEWALLRECORDS"));
+ }
+
+ @Test
+ void fromNameThrowsExceptionForUnknownName() {
+ String unknownName = "unknown_role";
+ Exception exception = assertThrows(IllegalArgumentException.class, () -> {
+ Role.fromName(unknownName);
+ });
+ assertEquals("Unknown role '" + unknownName + "'.", exception.getMessage());
+ }
+
+
+ @Test
+ void fromIriOrNameReturnsRoleByIri() {
+ assertEquals(Role.administrator, Role.fromIriOrName(Vocabulary.s_i_administrator));
+ assertEquals(Role.viewAllRecords, Role.fromIriOrName(Vocabulary.s_i_view_all_records_role));
+ }
+
+ @Test
+ void fromIriOrNameReturnsRoleByName() {
+ assertEquals(Role.administrator, Role.fromIriOrName("administrator"));
+ assertEquals(Role.viewAllRecords, Role.fromIriOrName("viewAllRecords"));
+ }
+
+ @Test
+ void fromIriOrNameIsCaseInsensitiveForName() {
+ assertEquals(Role.administrator, Role.fromIriOrName("ADMINISTRATOR"));
+ }
+
+ @Test
+ void fromIriOrNameThrowsExceptionForUnknownIdentifier() {
+ String unknownIdentifier = "unknown_identifier";
+ Exception exception = assertThrows(IllegalArgumentException.class, () -> {
+ Role.fromIriOrName(unknownIdentifier);
+ });
+ assertEquals("Unknown role '" + unknownIdentifier + "'.", exception.getMessage());
+ }
+}