From b1bbd54294b7ffe445b79afa9b17d1763b0453ea Mon Sep 17 00:00:00 2001
From: Lars Johansson <lars.johansson@ess.eu>
Date: Thu, 5 Jan 2023 17:38:13 +0100
Subject: [PATCH] Refactor structures services

---
 .../names/service/DeviceGroupService.java     | 145 +++++-
 .../names/service/DeviceTypeService.java      | 144 +++++-
 .../names/service/DisciplineService.java      | 145 +++++-
 .../openepics/names/service/NamesService.java |   3 +-
 .../names/service/StructuresService.java      | 471 +++---------------
 .../names/service/SubsystemService.java       | 144 +++++-
 .../names/service/SystemGroupService.java     | 144 +++++-
 .../names/service/SystemService.java          | 144 +++++-
 8 files changed, 894 insertions(+), 446 deletions(-)

diff --git a/src/main/java/org/openepics/names/service/DeviceGroupService.java b/src/main/java/org/openepics/names/service/DeviceGroupService.java
index 710dc550..245567ff 100644
--- a/src/main/java/org/openepics/names/service/DeviceGroupService.java
+++ b/src/main/java/org/openepics/names/service/DeviceGroupService.java
@@ -20,9 +20,11 @@ package org.openepics.names.service;
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.commons.lang3.StringUtils;
 import org.openepics.names.repository.DeviceGroupRepository;
 import org.openepics.names.repository.IDeviceGroupRepository;
 import org.openepics.names.repository.IDeviceTypeRepository;
@@ -31,6 +33,7 @@ import org.openepics.names.repository.model.DeviceType;
 import org.openepics.names.rest.beans.Status;
 import org.openepics.names.rest.beans.Type;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
+import org.openepics.names.util.EssNamingConvention;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
 import org.openepics.names.util.StructureCommand;
@@ -77,6 +80,71 @@ public class DeviceGroupService {
         this.deviceTypeService = deviceTypeService;
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification createStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        DeviceGroup deviceGroup = new DeviceGroup(UUID.randomUUID(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        deviceGroupRepository.createDeviceGroup(deviceGroup);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(deviceGroup),
+                NotificationUtil.prepareNotification(Type.DEVICEGROUP, StructureCommand.CREATE, null, null, deviceGroup, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification updateStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     find out previous
+        //     return
+        //         structure element for updated structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        DeviceGroup deviceGroup = new DeviceGroup(structureElement.getUuid(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        deviceGroupRepository.createDeviceGroup(deviceGroup);
+
+        // previous
+        List<DeviceGroup> previouses = iDeviceGroupRepository.findPreviousByUuidAndId(deviceGroup.getUuid().toString(),  deviceGroup.getId());
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(deviceGroup),
+                NotificationUtil.prepareNotification(Type.DEVICEGROUP, StructureCommand.UPDATE, null,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceGroup, holder));
+    }
+
     @Transactional(propagation = Propagation.MANDATORY)
     public StructureElementNotification deleteStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
         // validation outside method
@@ -88,10 +156,8 @@ public class DeviceGroupService {
         //         structure element for deleted structure
         //         notification
 
-        String uuid = structureElement.getUuid().toString();
-
         // find
-        List<DeviceGroup> deviceGroups = deviceGroupRepository.readDeviceGroups(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
+        List<DeviceGroup> deviceGroups = deviceGroupRepository.readDeviceGroups(Status.APPROVED, Boolean.FALSE, structureElement.getUuid().toString(), null, null, null, null, null, null);
         if (ValidateUtil.isNullOrNotSize(deviceGroups, 1)) {
             return null;
         }
@@ -138,7 +204,6 @@ public class DeviceGroupService {
         //         notification
 
         String uuid = structureElement.getUuid().toString();
-        String comment = structureElement.getComment();
 
         // find
         List<DeviceGroup> deviceGroups = deviceGroupRepository.readDeviceGroups(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
@@ -159,7 +224,7 @@ public class DeviceGroupService {
         deviceGroup = deviceGroups.get(0);
 
         // approve
-        deviceGroup.setAttributesStatusProcessed(Status.APPROVED, when, username, comment);
+        deviceGroup.setAttributesStatusProcessed(Status.APPROVED, when, username, structureElement.getComment());
         deviceGroup.setLatest(Boolean.TRUE);
         deviceGroupRepository.updateDeviceGroup(deviceGroup);
 
@@ -192,4 +257,74 @@ public class DeviceGroupService {
                 NotificationUtil.prepareNotification(Type.DEVICEGROUP, structureCommandCUD, StructureCommand.APPROVE, previous, deviceGroup, holder));
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification cancelStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     cancel - update structure to status CANCELLED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<DeviceGroup> deviceGroups = deviceGroupRepository.readDeviceGroups(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(deviceGroups, 1)) {
+            return null;
+        }
+        DeviceGroup deviceGroup = deviceGroups.get(0);
+
+        // cancel
+        deviceGroup.setAttributesStatusProcessed(Status.CANCELLED, when, username, structureElement.getComment());
+        deviceGroupRepository.updateDeviceGroup(deviceGroup);
+
+        // previous
+        List<DeviceGroup> previouses = iDeviceGroupRepository.findPreviousByUuidAndId(uuid, deviceGroup.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceGroup);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(deviceGroup, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.DEVICEGROUP, structureCommandCUD, StructureCommand.CANCEL,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceGroup, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification rejectStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     reject - update structure to status REJECTED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<DeviceGroup> deviceGroups = deviceGroupRepository.readDeviceGroups(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(deviceGroups, 1)) {
+            return null;
+        }
+        DeviceGroup deviceGroup = deviceGroups.get(0);
+
+        // reject
+        deviceGroup.setAttributesStatusProcessed(Status.REJECTED, when, username, structureElement.getComment());
+        deviceGroupRepository.updateDeviceGroup(deviceGroup);
+
+        // previous
+        List<DeviceGroup> previouses = iDeviceGroupRepository.findPreviousByUuidAndId(uuid, deviceGroup.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceGroup);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(deviceGroup, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.DEVICEGROUP, structureCommandCUD, StructureCommand.REJECT,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceGroup, holder));
+    }
+
 }
diff --git a/src/main/java/org/openepics/names/service/DeviceTypeService.java b/src/main/java/org/openepics/names/service/DeviceTypeService.java
index 309db086..f205b9de 100644
--- a/src/main/java/org/openepics/names/service/DeviceTypeService.java
+++ b/src/main/java/org/openepics/names/service/DeviceTypeService.java
@@ -20,15 +20,18 @@ package org.openepics.names.service;
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.commons.lang3.StringUtils;
 import org.openepics.names.repository.DeviceTypeRepository;
 import org.openepics.names.repository.IDeviceTypeRepository;
 import org.openepics.names.repository.model.DeviceType;
 import org.openepics.names.rest.beans.Status;
 import org.openepics.names.rest.beans.Type;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
+import org.openepics.names.util.EssNamingConvention;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
 import org.openepics.names.util.StructureCommand;
@@ -70,6 +73,71 @@ public class DeviceTypeService {
         this.namesService = namesService;
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification createStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        DeviceType deviceType = new DeviceType(UUID.randomUUID(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        deviceTypeRepository.createDeviceType(deviceType);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(deviceType),
+                NotificationUtil.prepareNotification(Type.DEVICETYPE, StructureCommand.CREATE, null, null, deviceType, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification updateStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     find out previous
+        //     return
+        //         structure element for updated structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        DeviceType deviceType = new DeviceType(structureElement.getUuid(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        deviceTypeRepository.createDeviceType(deviceType);
+
+        // previous
+        List<DeviceType> previouses = iDeviceTypeRepository.findPreviousByUuidAndId(deviceType.getUuid().toString(),  deviceType.getId());
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(deviceType),
+                NotificationUtil.prepareNotification(Type.DEVICETYPE, StructureCommand.UPDATE, null,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceType, holder));
+    }
+
     @Transactional(propagation = Propagation.MANDATORY)
     public StructureElementNotification deleteStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
         // validation outside method
@@ -81,10 +149,8 @@ public class DeviceTypeService {
         //         structure element for deleted structure
         //         notification
 
-        String uuid = structureElement.getUuid().toString();
-
         // find
-        List<DeviceType> deviceTypes = deviceTypeRepository.readDeviceTypes(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
+        List<DeviceType> deviceTypes = deviceTypeRepository.readDeviceTypes(Status.APPROVED, Boolean.FALSE, structureElement.getUuid().toString(), null, null, null, null, null, null);
         if (ValidateUtil.isNullOrNotSize(deviceTypes, 1)) {
             return null;
         }
@@ -131,7 +197,6 @@ public class DeviceTypeService {
         //         notification
 
         String uuid = structureElement.getUuid().toString();
-        String comment = structureElement.getComment();
 
         // find
         List<DeviceType> deviceTypes = deviceTypeRepository.readDeviceTypes(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
@@ -152,7 +217,7 @@ public class DeviceTypeService {
         deviceType = deviceTypes.get(0);
 
         // approve
-        deviceType.setAttributesStatusProcessed(Status.APPROVED, when, username, comment);
+        deviceType.setAttributesStatusProcessed(Status.APPROVED, when, username, structureElement.getComment());
         deviceType.setLatest(Boolean.TRUE);
         deviceTypeRepository.updateDeviceType(deviceType);
 
@@ -175,4 +240,73 @@ public class DeviceTypeService {
                 NotificationUtil.prepareNotification(Type.DEVICETYPE, structureCommandCUD, StructureCommand.APPROVE, previous, deviceType, holder));
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification cancelStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     cancel - update structure to status CANCELLED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        List<DeviceType> deviceTypes = deviceTypeRepository.readDeviceTypes(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(deviceTypes, 1)) {
+            return null;
+        }
+        DeviceType deviceType = deviceTypes.get(0);
+
+        // cancel
+        deviceType.setAttributesStatusProcessed(Status.CANCELLED, when, username, structureElement.getComment());
+        deviceTypeRepository.updateDeviceType(deviceType);
+
+        // previous
+        List<DeviceType> previouses = iDeviceTypeRepository.findPreviousByUuidAndId(uuid, deviceType.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceType);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(deviceType, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.DEVICETYPE, structureCommandCUD, StructureCommand.CANCEL,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceType, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification rejectStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     reject - update structure to status REJECTED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<DeviceType> deviceTypes = deviceTypeRepository.readDeviceTypes(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(deviceTypes, 1)) {
+            return null;
+        }
+        DeviceType deviceType = deviceTypes.get(0);
+
+        // reject
+        deviceType.setAttributesStatusProcessed(Status.REJECTED, when, username, structureElement.getComment());
+        deviceTypeRepository.updateDeviceType(deviceType);
+
+        // previous
+        List<DeviceType> previouses = iDeviceTypeRepository.findPreviousByUuidAndId(uuid, deviceType.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceType);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(deviceType, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.DEVICETYPE, structureCommandCUD, StructureCommand.REJECT,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceType, holder));
+    }
+
 }
diff --git a/src/main/java/org/openepics/names/service/DisciplineService.java b/src/main/java/org/openepics/names/service/DisciplineService.java
index b9685d10..d5f955be 100644
--- a/src/main/java/org/openepics/names/service/DisciplineService.java
+++ b/src/main/java/org/openepics/names/service/DisciplineService.java
@@ -20,9 +20,11 @@ package org.openepics.names.service;
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.commons.lang3.StringUtils;
 import org.openepics.names.repository.DisciplineRepository;
 import org.openepics.names.repository.IDeviceGroupRepository;
 import org.openepics.names.repository.IDisciplineRepository;
@@ -31,6 +33,7 @@ import org.openepics.names.repository.model.Discipline;
 import org.openepics.names.rest.beans.Status;
 import org.openepics.names.rest.beans.Type;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
+import org.openepics.names.util.EssNamingConvention;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
 import org.openepics.names.util.StructureCommand;
@@ -80,6 +83,71 @@ public class DisciplineService {
         this.deviceGroupService = deviceGroupService;
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification createStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        Discipline discipline = new Discipline(UUID.randomUUID(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        disciplineRepository.createDiscipline(discipline);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(discipline),
+                NotificationUtil.prepareNotification(Type.DISCIPLINE, StructureCommand.CREATE, null, null, discipline, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification updateStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     find out previous
+        //     return
+        //         structure element for updated structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        Discipline discipline = new Discipline(structureElement.getUuid(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        disciplineRepository.createDiscipline(discipline);
+
+        // previous
+        List<Discipline> previouses = iDisciplineRepository.findPreviousByUuidAndId(discipline.getUuid().toString(),  discipline.getId());
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(discipline),
+                NotificationUtil.prepareNotification(Type.DISCIPLINE, StructureCommand.UPDATE, null,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, discipline, holder));
+    }
+
     @Transactional(propagation = Propagation.MANDATORY)
     public StructureElementNotification deleteStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
         // validation outside method
@@ -91,10 +159,8 @@ public class DisciplineService {
         //         structure element for deleted structure
         //         notification
 
-        String uuid = structureElement.getUuid().toString();
-
         // find
-        List<Discipline> disciplines = disciplineRepository.readDisciplines(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null);
+        List<Discipline> disciplines = disciplineRepository.readDisciplines(Status.APPROVED, Boolean.FALSE, structureElement.getUuid().toString(), null, null, null, null, null);
         if (ValidateUtil.isNullOrNotSize(disciplines, 1)) {
             return null;
         }
@@ -141,7 +207,6 @@ public class DisciplineService {
         //         notification
 
         String uuid = structureElement.getUuid().toString();
-        String comment = structureElement.getComment();
 
         List<Discipline> disciplines = disciplineRepository.readDisciplines(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null);
         Discipline discipline = null;
@@ -161,7 +226,7 @@ public class DisciplineService {
         discipline = disciplines.get(0);
 
         // approve
-        discipline.setAttributesStatusProcessed(Status.APPROVED, when, username, comment);
+        discipline.setAttributesStatusProcessed(Status.APPROVED, when, username, structureElement.getComment());
         discipline.setLatest(Boolean.TRUE);
         disciplineRepository.updateDiscipline(discipline);
 
@@ -196,4 +261,74 @@ public class DisciplineService {
                 NotificationUtil.prepareNotification(Type.DISCIPLINE, structureCommandCUD, StructureCommand.APPROVE, previous, discipline, holder));
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification cancelStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     cancel - update structure to status CANCELLED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<Discipline> disciplines = disciplineRepository.readDisciplines(Status.PENDING, null, uuid, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(disciplines, 1)) {
+            return null;
+        }
+        Discipline discipline = disciplines.get(0);
+
+        // cancel
+        discipline.setAttributesStatusProcessed(Status.CANCELLED, when, username, structureElement.getComment());
+        disciplineRepository.updateDiscipline(discipline);
+
+        // previous
+        List<Discipline> previouses = iDisciplineRepository.findPreviousByUuidAndId(uuid, discipline.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, discipline);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(discipline, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.DISCIPLINE, structureCommandCUD, StructureCommand.CANCEL,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, discipline, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification rejectStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     reject - update structure to status REJECTED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<Discipline> disciplines = disciplineRepository.readDisciplines(Status.PENDING, null, uuid, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(disciplines, 1)) {
+            return null;
+        }
+        Discipline discipline = disciplines.get(0);
+
+        // reject
+        discipline.setAttributesStatusProcessed(Status.REJECTED, when, username, structureElement.getComment());
+        disciplineRepository.updateDiscipline(discipline);
+
+        // previous
+        List<Discipline> previouses = iDisciplineRepository.findPreviousByUuidAndId(uuid, discipline.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, discipline);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(discipline, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.DISCIPLINE, structureCommandCUD, StructureCommand.REJECT,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, discipline, holder));
+    }
+
 }
diff --git a/src/main/java/org/openepics/names/service/NamesService.java b/src/main/java/org/openepics/names/service/NamesService.java
index 8f911dae..a13cd589 100644
--- a/src/main/java/org/openepics/names/service/NamesService.java
+++ b/src/main/java/org/openepics/names/service/NamesService.java
@@ -94,12 +94,11 @@ public class NamesService {
 
     private static final String UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE = "Update after APPROVE structure change";
 
-    private EssNamingConvention namingConvention;
-
     private HolderIRepositories holderIRepositories;
     private HolderRepositories holderRepositories;
     // convenience, also part of holderRepositories
     private NameRepository nameRepository;
+    private EssNamingConvention namingConvention;
 
     @Autowired
     public NamesService(
diff --git a/src/main/java/org/openepics/names/service/StructuresService.java b/src/main/java/org/openepics/names/service/StructuresService.java
index 498ad53e..53ac5c3a 100644
--- a/src/main/java/org/openepics/names/service/StructuresService.java
+++ b/src/main/java/org/openepics/names/service/StructuresService.java
@@ -20,7 +20,6 @@ package org.openepics.names.service;
 
 import java.util.Date;
 import java.util.List;
-import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -62,7 +61,6 @@ import org.openepics.names.util.Utilities;
 import org.openepics.names.util.ValidateStructureElementUtil;
 import org.openepics.names.util.ValidateUtil;
 import org.openepics.names.util.notification.NotificationStructure;
-import org.openepics.names.util.notification.NotificationUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -93,8 +91,6 @@ public class StructuresService {
     protected static final String SYSTEM_STRUCTURE_ONLY                 = "System structure only";
     protected static final String DELETE_AFTER_APPROVE_STRUCTURE_CHANGE = "Delete after APPROVE structure change";
 
-    private EssNamingConvention namingConvention;
-
     private HolderIRepositories holderIRepositories;
     private HolderRepositories holderRepositories;
     private SystemGroupService systemGroupService;
@@ -104,6 +100,7 @@ public class StructuresService {
     private DeviceGroupService deviceGroupService;
     private DeviceTypeService deviceTypeService;
     private NotificationService notificationService;
+    private EssNamingConvention namingConvention;
 
     @Autowired
     public StructuresService(
@@ -160,7 +157,7 @@ public class StructuresService {
         // validation outside method
         // transaction
         //     for each structure element command
-        //         create structure to pending, not latest, not deleted, with data
+        //         create structure
         //         handle
         //             notification
         //             structure element for created structure
@@ -176,86 +173,27 @@ public class StructuresService {
         List<NotificationStructure> notifications = Lists.newArrayList();
         final List<StructureElement> createdStructureElements = Lists.newArrayList();
         for (StructureElementCommand structureElement : structureElements) {
-            // note
-            //     namingConvention.equivalenceClassRepresentative return null for null input
-            //     rules for mnemonic for system group, device group
-
-            UUID uuid = UUID.randomUUID();
             Type type = structureElement.getType();
-            String name = structureElement.getName();
-            String mnemonic = structureElement.getMnemonic();
-            mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
-            String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
-            String description = structureElement.getDescription();
-            String comment = structureElement.getComment();
+            StructureElementNotification structureElementNotification = null;
 
             if (Type.SYSTEMGROUP.equals(type)) {
-                // create
-                SystemGroup systemGroup = new SystemGroup(uuid,
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getSystemGroupRepository().createSystemGroup(systemGroup);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.CREATE, null, null, systemGroup, holder);
-                createdStructureElements.add(StructureElementUtil.getStructureElementRequested(systemGroup));
+                structureElementNotification = systemGroupService.createStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.SYSTEM.equals(type)) {
-                // create
-                System system = new System(uuid, structureElement.getParent(),
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getSystemRepository().createSystem(system);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.CREATE, null, null, system, holder);
-                createdStructureElements.add(StructureElementUtil.getStructureElementRequested(system));
+                structureElementNotification = systemService.createStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.SUBSYSTEM.equals(type)) {
-                // create
-                Subsystem subsystem = new Subsystem(uuid, structureElement.getParent(),
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getSubsystemRepository().createSubsystem(subsystem);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.CREATE, null, null, subsystem, holder);
-                createdStructureElements.add(StructureElementUtil.getStructureElementRequested(subsystem));
+                structureElementNotification = subsystemService.createStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.DISCIPLINE.equals(type)) {
-                // create
-                Discipline discipline = new Discipline(uuid,
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getDisciplineRepository().createDiscipline(discipline);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.CREATE, null, null, discipline, holder);
-                createdStructureElements.add(StructureElementUtil.getStructureElementRequested(discipline));
+                structureElementNotification = disciplineService.createStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.DEVICEGROUP.equals(type)) {
-                // create
-                DeviceGroup deviceGroup = new DeviceGroup(uuid, structureElement.getParent(),
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getDeviceGroupRepository().createDeviceGroup(deviceGroup);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.CREATE, null, null, deviceGroup, holder);
-                createdStructureElements.add(StructureElementUtil.getStructureElementRequested(deviceGroup));
+                structureElementNotification = deviceGroupService.createStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.DEVICETYPE.equals(type)) {
-                // create
-                DeviceType deviceType = new DeviceType(uuid, structureElement.getParent(),
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getDeviceTypeRepository().createDeviceType(deviceType);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.CREATE, null, null, deviceType, holder);
-                createdStructureElements.add(StructureElementUtil.getStructureElementRequested(deviceType));
+                structureElementNotification = deviceTypeService.createStructure(structureElement, when, username, namingConvention, holder);
+            } else {
+                continue;
             }
+
+            Utilities.addToCollection(notifications, structureElementNotification.notificationStructure());
+            Utilities.addToCollection(createdStructureElements, structureElementNotification.structureElement());
         }
 
         // notify
@@ -792,8 +730,7 @@ public class StructuresService {
         // validation outside method
         // transaction
         //     for each structure element command
-        //         create structure to pending, not latest, not deleted, with data
-        //         find out previous
+        //         update structure
         //         handle
         //             notification
         //             structure element for updated structure
@@ -809,110 +746,27 @@ public class StructuresService {
         List<NotificationStructure> notifications = Lists.newArrayList();
         final List<StructureElement> updatedStructureElements = Lists.newArrayList();
         for (StructureElementCommand structureElement : structureElements) {
-            // note
-            //     namingConvention.equivalenceClassRepresentative return null for null input
-            //     rules for mnemonic for system group, device group
-
-            UUID uuid = structureElement.getUuid();
             Type type = structureElement.getType();
-            String name = structureElement.getName();
-            String mnemonic = structureElement.getMnemonic();
-            mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
-            String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
-            String description = structureElement.getDescription();
-            String comment = structureElement.getComment();
+            StructureElementNotification structureElementNotification = null;
 
             if (Type.SYSTEMGROUP.equals(type)) {
-                // create
-                SystemGroup systemGroup = new SystemGroup(uuid,
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getSystemGroupRepository().createSystemGroup(systemGroup);
-
-                // previous
-                List<SystemGroup> previouses = holderIRepositories.getSystemGroupRepository().findPreviousByUuidAndId(uuid.toString(),  systemGroup.getId());
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.UPDATE, null,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, systemGroup, holder);
-                updatedStructureElements.add(StructureElementUtil.getStructureElementRequested(systemGroup));
+                structureElementNotification = systemGroupService.updateStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.SYSTEM.equals(type)) {
-                // create
-                System system = new System(uuid, structureElement.getParent(),
-                        name, structureElement.getMnemonic(), equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getSystemRepository().createSystem(system);
-
-                // previous
-                List<System> previouses = holderIRepositories.getSystemRepository().findPreviousByUuidAndId(uuid.toString(),  system.getId());
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.UPDATE, null,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, system, holder);
-                updatedStructureElements.add(StructureElementUtil.getStructureElementRequested(system));
+                structureElementNotification = systemService.updateStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.SUBSYSTEM.equals(type)) {
-                // create
-                Subsystem subsystem = new Subsystem(uuid, structureElement.getParent(),
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getSubsystemRepository().createSubsystem(subsystem);
-
-                // previous
-                List<Subsystem> previouses = holderIRepositories.getSubsystemRepository().findPreviousByUuidAndId(uuid.toString(),  subsystem.getId());
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.UPDATE, null,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, subsystem, holder);
-                updatedStructureElements.add(StructureElementUtil.getStructureElementRequested(subsystem));
+                structureElementNotification = subsystemService.updateStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.DISCIPLINE.equals(type)) {
-                // create
-                Discipline discipline = new Discipline(uuid,
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getDisciplineRepository().createDiscipline(discipline);
-
-                // previous
-                List<Discipline> previouses = holderIRepositories.getDisciplineRepository().findPreviousByUuidAndId(uuid.toString(),  discipline.getId());
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.UPDATE, null,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, discipline, holder);
-                updatedStructureElements.add(StructureElementUtil.getStructureElementRequested(discipline));
+                structureElementNotification = disciplineService.updateStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.DEVICEGROUP.equals(type)) {
-                // create
-                DeviceGroup deviceGroup = new DeviceGroup(uuid, structureElement.getParent(),
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getDeviceGroupRepository().createDeviceGroup(deviceGroup);
-
-                // previous
-                List<DeviceGroup> previouses = holderIRepositories.getDeviceGroupRepository().findPreviousByUuidAndId(uuid.toString(),  deviceGroup.getId());
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.UPDATE, null,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceGroup, holder);
-                updatedStructureElements.add(StructureElementUtil.getStructureElementRequested(deviceGroup));
+                structureElementNotification = deviceGroupService.updateStructure(structureElement, when, username, namingConvention, holder);
             } else if (Type.DEVICETYPE.equals(type)) {
-                // create
-                DeviceType deviceType = new DeviceType(uuid, structureElement.getParent(),
-                        name, mnemonic, equivalenceClassRepresentative,
-                        description, Status.PENDING, Boolean.FALSE, Boolean.FALSE,
-                        when, username, comment);
-                holderRepositories.getDeviceTypeRepository().createDeviceType(deviceType);
-
-                // previous
-                List<DeviceType> previouses = holderIRepositories.getDeviceTypeRepository().findPreviousByUuidAndId(uuid.toString(),  deviceType.getId());
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, StructureCommand.UPDATE, null,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceType, holder);
-                updatedStructureElements.add(StructureElementUtil.getStructureElementRequested(deviceType));
+                structureElementNotification = deviceTypeService.updateStructure(structureElement, when, username, namingConvention, holder);
+            } else {
+                continue;
             }
+
+            Utilities.addToCollection(notifications, structureElementNotification.notificationStructure());
+            Utilities.addToCollection(updatedStructureElements, structureElementNotification.structureElement());
         }
 
         // notify
@@ -1039,10 +893,8 @@ public class StructuresService {
     public List<StructureElement> cancelStructures(List<StructureElementCommand> structureElements, String username) {
         // validation outside method
         // transaction
-        //     for each structure element
-        //         find
-        //         cancel - update structure to status CANCELLED
-        //         find out previous
+        //     for each structure element command
+        //         cancel structure
         //         handle
         //             notification
         //             structure element for cancelled structure
@@ -1058,130 +910,27 @@ public class StructuresService {
         List<NotificationStructure> notifications = Lists.newArrayList();
         final List<StructureElement> cancelledStructureElements = Lists.newArrayList();
         for (StructureElementCommand structureElement : structureElements) {
-            String uuid = structureElement.getUuid().toString();
             Type type = structureElement.getType();
-            String comment = structureElement.getComment();
+            StructureElementNotification structureElementNotification = null;
 
             if (Type.SYSTEMGROUP.equals(type)) {
-                // find
-                List<SystemGroup> systemGroups = holderRepositories.getSystemGroupRepository().readSystemGroups(Status.PENDING, null, uuid, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(systemGroups, 1)) {
-                    continue;
-                }
-                SystemGroup systemGroup = systemGroups.get(0);
-
-                // cancel
-                systemGroup.setAttributesStatusProcessed(Status.CANCELLED, when, username, comment);
-                holderRepositories.getSystemGroupRepository().updateSystemGroup(systemGroup);
-
-                // previous
-                List<SystemGroup> previouses = holderIRepositories.getSystemGroupRepository().findPreviousByUuidAndId(uuid, systemGroup.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, systemGroup);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.CANCEL,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, systemGroup, holder);
-                cancelledStructureElements.add(StructureElementUtil.getStructureElementProcessed(systemGroup, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = systemGroupService.cancelStructure(structureElement, when, username, holder);
             } else if (Type.SYSTEM.equals(type)) {
-                // find
-                List<System> systems = holderRepositories.getSystemRepository().readSystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(systems, 1)) {
-                    continue;
-                }
-                System system = systems.get(0);
-
-                // cancel
-                system.setAttributesStatusProcessed(Status.CANCELLED, when, username, comment);
-                holderRepositories.getSystemRepository().updateSystem(system);
-
-                // previous
-                List<System> previouses = holderIRepositories.getSystemRepository().findPreviousByUuidAndId(uuid, system.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, system);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.CANCEL,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, system, holder);
-                cancelledStructureElements.add(StructureElementUtil.getStructureElementProcessed(system, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = systemService.cancelStructure(structureElement, when, username, holder);
             } else if (Type.SUBSYSTEM.equals(type)) {
-                // find
-                List<Subsystem> subsystems = holderRepositories.getSubsystemRepository().readSubsystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(subsystems, 1)) {
-                    continue;
-                }
-                Subsystem subsystem = subsystems.get(0);
-
-                // cancel
-                subsystem.setAttributesStatusProcessed(Status.CANCELLED, when, username, comment);
-                holderRepositories.getSubsystemRepository().updateSubsystem(subsystem);
-
-                // previous
-                List<Subsystem> previouses = holderIRepositories.getSubsystemRepository().findPreviousByUuidAndId(uuid, subsystem.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, subsystem);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.CANCEL,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, subsystem, holder);
-                cancelledStructureElements.add(StructureElementUtil.getStructureElementProcessed(subsystem, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = subsystemService.cancelStructure(structureElement, when, username, holder);
             } else if (Type.DISCIPLINE.equals(type)) {
-                // find
-                List<Discipline> disciplines = holderRepositories.getDisciplineRepository().readDisciplines(Status.PENDING, null, uuid, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(disciplines, 1)) {
-                    continue;
-                }
-                Discipline discipline = disciplines.get(0);
-
-                // cancel
-                discipline.setAttributesStatusProcessed(Status.CANCELLED, when, username, comment);
-                holderRepositories.getDisciplineRepository().updateDiscipline(discipline);
-
-                // previous
-                List<Discipline> previouses = holderIRepositories.getDisciplineRepository().findPreviousByUuidAndId(uuid, discipline.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, discipline);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.CANCEL,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, discipline, holder);
-                cancelledStructureElements.add(StructureElementUtil.getStructureElementProcessed(discipline, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = disciplineService.cancelStructure(structureElement, when, username, holder);
             } else if (Type.DEVICEGROUP.equals(type)) {
-                // find
-                List<DeviceGroup> deviceGroups = holderRepositories.getDeviceGroupRepository().readDeviceGroups(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(deviceGroups, 1)) {
-                    continue;
-                }
-                DeviceGroup deviceGroup = deviceGroups.get(0);
-
-                // cancel
-                deviceGroup.setAttributesStatusProcessed(Status.CANCELLED, when, username, comment);
-                holderRepositories.getDeviceGroupRepository().updateDeviceGroup(deviceGroup);
-
-                // previous
-                List<DeviceGroup> previouses = holderIRepositories.getDeviceGroupRepository().findPreviousByUuidAndId(uuid, deviceGroup.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceGroup);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.CANCEL,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceGroup, holder);
-                cancelledStructureElements.add(StructureElementUtil.getStructureElementProcessed(deviceGroup, holder, StructureChoice.STRUCTURE));
-            } else if (Type.DEVICETYPE.equals(type)) {
-                List<DeviceType> deviceTypes = holderRepositories.getDeviceTypeRepository().readDeviceTypes(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(deviceTypes, 1)) {
-                    continue;
-                }
-                DeviceType deviceType = deviceTypes.get(0);
-
-                // cancel
-                deviceType.setAttributesStatusProcessed(Status.CANCELLED, when, username, comment);
-                holderRepositories.getDeviceTypeRepository().updateDeviceType(deviceType);
-
-                // previous
-                List<DeviceType> previouses = holderIRepositories.getDeviceTypeRepository().findPreviousByUuidAndId(uuid, deviceType.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceType);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.CANCEL,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceType, holder);
-                cancelledStructureElements.add(StructureElementUtil.getStructureElementProcessed(deviceType, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = deviceGroupService.cancelStructure(structureElement, when, username, holder);
+            } else if (Type.DEVICETYPE.equals(structureElement.getType())) {
+                structureElementNotification = deviceTypeService.cancelStructure(structureElement, when, username, holder);
+            } else {
+                continue;
             }
+
+            Utilities.addToCollection(notifications, structureElementNotification.notificationStructure());
+            Utilities.addToCollection(cancelledStructureElements, structureElementNotification.structureElement());
         }
 
         // notify
@@ -1195,10 +944,8 @@ public class StructuresService {
     public List<StructureElement> rejectStructures(List<StructureElementCommand> structureElements, String username) {
         // validation outside method
         // transaction
-        //     for each structure element
-        //         find
-        //         reject - update structure to status REJECTED
-        //         find out previous
+        //     for each structure element command
+        //         reject structure
         //         handle
         //             notification
         //             structure element for rejected structure
@@ -1214,131 +961,27 @@ public class StructuresService {
         List<NotificationStructure> notifications = Lists.newArrayList();
         final List<StructureElement> rejectedStructureElements = Lists.newArrayList();
         for (StructureElementCommand structureElement : structureElements) {
-            String uuid = structureElement.getUuid().toString();
             Type type = structureElement.getType();
-            String comment = structureElement.getComment();
+            StructureElementNotification structureElementNotification = null;
 
             if (Type.SYSTEMGROUP.equals(type)) {
-                // find
-                List<SystemGroup> systemGroups = holderRepositories.getSystemGroupRepository().readSystemGroups(Status.PENDING, null, uuid, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(systemGroups, 1)) {
-                    continue;
-                }
-                SystemGroup systemGroup = systemGroups.get(0);
-
-                // reject
-                systemGroup.setAttributesStatusProcessed(Status.REJECTED, when, username, comment);
-                holderRepositories.getSystemGroupRepository().updateSystemGroup(systemGroup);
-
-                // previous
-                List<SystemGroup> previouses = holderIRepositories.getSystemGroupRepository().findPreviousByUuidAndId(uuid, systemGroup.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, systemGroup);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.REJECT,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, systemGroup, holder);
-                rejectedStructureElements.add(StructureElementUtil.getStructureElementProcessed(systemGroup, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = systemGroupService.rejectStructure(structureElement, when, username, holder);
             } else if (Type.SYSTEM.equals(type)) {
-                // find
-                List<System> systems = holderRepositories.getSystemRepository().readSystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(systems, 1)) {
-                    continue;
-                }
-                System system = systems.get(0);
-
-                // reject
-                system.setAttributesStatusProcessed(Status.REJECTED, when, username, comment);
-                holderRepositories.getSystemRepository().updateSystem(system);
-
-                // previous
-                List<System> previouses = holderIRepositories.getSystemRepository().findPreviousByUuidAndId(uuid, system.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, system);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.REJECT,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, system, holder);
-                rejectedStructureElements.add(StructureElementUtil.getStructureElementProcessed(system, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = systemService.rejectStructure(structureElement, when, username, holder);
             } else if (Type.SUBSYSTEM.equals(type)) {
-                // find
-                List<Subsystem> subsystems = holderRepositories.getSubsystemRepository().readSubsystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(subsystems, 1)) {
-                    continue;
-                }
-                Subsystem subsystem = subsystems.get(0);
-
-                // reject
-                subsystem.setAttributesStatusProcessed(Status.REJECTED, when, username, comment);
-                holderRepositories.getSubsystemRepository().updateSubsystem(subsystem);
-
-                // previous
-                List<Subsystem> previouses = holderIRepositories.getSubsystemRepository().findPreviousByUuidAndId(uuid, subsystem.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, subsystem);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.REJECT,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, subsystem, holder);
-                rejectedStructureElements.add(StructureElementUtil.getStructureElementProcessed(subsystem, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = subsystemService.rejectStructure(structureElement, when, username, holder);
             } else if (Type.DISCIPLINE.equals(type)) {
-                // find
-                List<Discipline> disciplines = holderRepositories.getDisciplineRepository().readDisciplines(Status.PENDING, null, uuid, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(disciplines, 1)) {
-                    continue;
-                }
-                Discipline discipline = disciplines.get(0);
-
-                // reject
-                discipline.setAttributesStatusProcessed(Status.REJECTED, when, username, comment);
-                holderRepositories.getDisciplineRepository().updateDiscipline(discipline);
-
-                // previous
-                List<Discipline> previouses = holderIRepositories.getDisciplineRepository().findPreviousByUuidAndId(uuid, discipline.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, discipline);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.REJECT,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, discipline, holder);
-                rejectedStructureElements.add(StructureElementUtil.getStructureElementProcessed(discipline, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = disciplineService.rejectStructure(structureElement, when, username, holder);
             } else if (Type.DEVICEGROUP.equals(type)) {
-                // find
-                List<DeviceGroup> deviceGroups = holderRepositories.getDeviceGroupRepository().readDeviceGroups(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(deviceGroups, 1)) {
-                    continue;
-                }
-                DeviceGroup deviceGroup = deviceGroups.get(0);
-
-                // reject
-                deviceGroup.setAttributesStatusProcessed(Status.REJECTED, when, username, comment);
-                holderRepositories.getDeviceGroupRepository().updateDeviceGroup(deviceGroup);
-
-                // previous
-                List<DeviceGroup> previouses = holderIRepositories.getDeviceGroupRepository().findPreviousByUuidAndId(uuid, deviceGroup.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceGroup);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.REJECT,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceGroup, holder);
-                rejectedStructureElements.add(StructureElementUtil.getStructureElementProcessed(deviceGroup, holder, StructureChoice.STRUCTURE));
-            } else if (Type.DEVICETYPE.equals(type)) {
-                // find
-                List<DeviceType> deviceTypes = holderRepositories.getDeviceTypeRepository().readDeviceTypes(Status.PENDING, null, uuid, null, null, null, null, null, null);
-                if (ValidateUtil.isNullOrNotSize(deviceTypes, 1)) {
-                    continue;
-                }
-                DeviceType deviceType = deviceTypes.get(0);
-
-                // reject
-                deviceType.setAttributesStatusProcessed(Status.REJECTED, when, username, comment);
-                holderRepositories.getDeviceTypeRepository().updateDeviceType(deviceType);
-
-                // previous
-                List<DeviceType> previouses = holderIRepositories.getDeviceTypeRepository().findPreviousByUuidAndId(uuid, deviceType.getId());
-                StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, deviceType);
-
-                // handle
-                NotificationUtil.prepareAddNotification(notifications, type, structureCommandCUD, StructureCommand.REJECT,
-                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, deviceType, holder);
-                rejectedStructureElements.add(StructureElementUtil.getStructureElementProcessed(deviceType, holder, StructureChoice.STRUCTURE));
+                structureElementNotification = deviceGroupService.rejectStructure(structureElement, when, username, holder);
+            } else if (Type.DEVICETYPE.equals(structureElement.getType())) {
+                structureElementNotification = deviceTypeService.rejectStructure(structureElement, when, username, holder);
+            } else {
+                continue;
             }
+
+            Utilities.addToCollection(notifications, structureElementNotification.notificationStructure());
+            Utilities.addToCollection(rejectedStructureElements, structureElementNotification.structureElement());
         }
 
         // notify
diff --git a/src/main/java/org/openepics/names/service/SubsystemService.java b/src/main/java/org/openepics/names/service/SubsystemService.java
index ce61c738..877782e8 100644
--- a/src/main/java/org/openepics/names/service/SubsystemService.java
+++ b/src/main/java/org/openepics/names/service/SubsystemService.java
@@ -20,6 +20,7 @@ package org.openepics.names.service;
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -32,6 +33,7 @@ import org.openepics.names.rest.beans.Type;
 import org.openepics.names.rest.beans.element.NameElement;
 import org.openepics.names.rest.beans.element.NameElementCommand;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
+import org.openepics.names.util.EssNamingConvention;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
 import org.openepics.names.util.StructureCommand;
@@ -73,6 +75,71 @@ public class SubsystemService {
         this.namesService = namesService;
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification createStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        Subsystem subsystem = new Subsystem(UUID.randomUUID(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        subsystemRepository.createSubsystem(subsystem);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(subsystem),
+                NotificationUtil.prepareNotification(Type.SUBSYSTEM, StructureCommand.CREATE, null, null, subsystem, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification updateStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     find out previous
+        //     return
+        //         structure element for updated structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        Subsystem subsystem = new Subsystem(structureElement.getUuid(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        subsystemRepository.createSubsystem(subsystem);
+
+        // previous
+        List<Subsystem> previouses = iSubsystemRepository.findPreviousByUuidAndId(subsystem.getUuid().toString(),  subsystem.getId());
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(subsystem),
+                NotificationUtil.prepareNotification(Type.SUBSYSTEM, StructureCommand.UPDATE, null,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, subsystem, holder));
+    }
+
     @Transactional(propagation = Propagation.MANDATORY)
     public StructureElementNotification deleteStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
         // validation outside method
@@ -84,10 +151,8 @@ public class SubsystemService {
         //         structure element for deleted structure
         //         notification
 
-        String uuid = structureElement.getUuid().toString();
-
         // find
-        List<Subsystem> subsystems = subsystemRepository.readSubsystems(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
+        List<Subsystem> subsystems = subsystemRepository.readSubsystems(Status.APPROVED, Boolean.FALSE, structureElement.getUuid().toString(), null, null, null, null, null, null);
         if (ValidateUtil.isNullOrNotSize(subsystems, 1)) {
             return null;
         }
@@ -134,7 +199,6 @@ public class SubsystemService {
         //         notification
 
         String uuid = structureElement.getUuid().toString();
-        String processedComment = structureElement.getComment();
 
         // find
         List<Subsystem> subsystems = subsystemRepository.readSubsystems(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
@@ -155,7 +219,7 @@ public class SubsystemService {
         subsystem = subsystems.get(0);
 
         // approve
-        subsystem.setAttributesStatusProcessed(Status.APPROVED, when, username, processedComment);
+        subsystem.setAttributesStatusProcessed(Status.APPROVED, when, username, structureElement.getComment());
         subsystem.setLatest(Boolean.TRUE);
         subsystemRepository.updateSubsystem(subsystem);
 
@@ -186,4 +250,74 @@ public class SubsystemService {
                 NotificationUtil.prepareNotification(Type.SUBSYSTEM, structureCommandCUD, StructureCommand.APPROVE, previous, subsystem, holder));
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification cancelStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     cancel - update structure to status CANCELLED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<Subsystem> subsystems = subsystemRepository.readSubsystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(subsystems, 1)) {
+            return null;
+        }
+        Subsystem subsystem = subsystems.get(0);
+
+        // cancel
+        subsystem.setAttributesStatusProcessed(Status.CANCELLED, when, username, structureElement.getComment());
+        subsystemRepository.updateSubsystem(subsystem);
+
+        // previous
+        List<Subsystem> previouses = iSubsystemRepository.findPreviousByUuidAndId(uuid, subsystem.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, subsystem);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(subsystem, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.SUBSYSTEM, structureCommandCUD, StructureCommand.CANCEL,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, subsystem, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification rejectStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     reject - update structure to status REJECTED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<Subsystem> subsystems = subsystemRepository.readSubsystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(subsystems, 1)) {
+            return null;
+        }
+        Subsystem subsystem = subsystems.get(0);
+
+        // reject
+        subsystem.setAttributesStatusProcessed(Status.REJECTED, when, username, structureElement.getComment());
+        subsystemRepository.updateSubsystem(subsystem);
+
+        // previous
+        List<Subsystem> previouses = iSubsystemRepository.findPreviousByUuidAndId(uuid, subsystem.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, subsystem);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(subsystem, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.SUBSYSTEM, structureCommandCUD, StructureCommand.REJECT,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, subsystem, holder));
+    }
+
 }
diff --git a/src/main/java/org/openepics/names/service/SystemGroupService.java b/src/main/java/org/openepics/names/service/SystemGroupService.java
index 86f3cf0b..a7ff1619 100644
--- a/src/main/java/org/openepics/names/service/SystemGroupService.java
+++ b/src/main/java/org/openepics/names/service/SystemGroupService.java
@@ -20,6 +20,7 @@ package org.openepics.names.service;
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -34,6 +35,7 @@ import org.openepics.names.rest.beans.Type;
 import org.openepics.names.rest.beans.element.NameElement;
 import org.openepics.names.rest.beans.element.NameElementCommand;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
+import org.openepics.names.util.EssNamingConvention;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
 import org.openepics.names.util.StructureCommand;
@@ -83,6 +85,71 @@ public class SystemGroupService {
         this.systemService = systemService;
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification createStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        SystemGroup systemGroup = new SystemGroup(UUID.randomUUID(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        systemGroupRepository.createSystemGroup(systemGroup);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(systemGroup),
+                NotificationUtil.prepareNotification(Type.SYSTEMGROUP, StructureCommand.CREATE, null, null, systemGroup, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification updateStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     find out previous
+        //     return
+        //         structure element for updated structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        SystemGroup systemGroup = new SystemGroup(structureElement.getUuid(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        systemGroupRepository.createSystemGroup(systemGroup);
+
+        // previous
+        List<SystemGroup> previouses = iSystemGroupRepository.findPreviousByUuidAndId(systemGroup.getUuid().toString(),  systemGroup.getId());
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(systemGroup),
+                NotificationUtil.prepareNotification(Type.SYSTEMGROUP, StructureCommand.UPDATE, null,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, systemGroup, holder));
+    }
+
     @Transactional(propagation = Propagation.MANDATORY)
     public StructureElementNotification deleteStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
         // validation outside method
@@ -94,10 +161,8 @@ public class SystemGroupService {
         //         structure element for deleted structure
         //         notification
 
-        String uuid = structureElement.getUuid().toString();
-
         // find
-        List<SystemGroup> systemGroups = systemGroupRepository.readSystemGroups(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null);
+        List<SystemGroup> systemGroups = systemGroupRepository.readSystemGroups(Status.APPROVED, Boolean.FALSE, structureElement.getUuid().toString(), null, null, null, null, null);
         if (ValidateUtil.isNullOrNotSize(systemGroups, 1)) {
             return null;
         }
@@ -144,7 +209,6 @@ public class SystemGroupService {
         //         notification
 
         String uuid = structureElement.getUuid().toString();
-        String comment = structureElement.getComment();
 
         // find
         List<SystemGroup> systemGroups = systemGroupRepository.readSystemGroups(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null);
@@ -165,7 +229,7 @@ public class SystemGroupService {
         systemGroup = systemGroups.get(0);
 
         // approve
-        systemGroup.setAttributesStatusProcessed(Status.APPROVED, when, username, comment);
+        systemGroup.setAttributesStatusProcessed(Status.APPROVED, when, username, structureElement.getComment());
         systemGroup.setLatest(Boolean.TRUE);
         systemGroupRepository.updateSystemGroup(systemGroup);
 
@@ -207,4 +271,74 @@ public class SystemGroupService {
                 NotificationUtil.prepareNotification(Type.SYSTEMGROUP, structureCommandCUD, StructureCommand.APPROVE, previous, systemGroup, holder));
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification cancelStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     cancel - update structure to status CANCELLED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<SystemGroup> systemGroups = systemGroupRepository.readSystemGroups(Status.PENDING, null, uuid, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(systemGroups, 1)) {
+            return null;
+        }
+        SystemGroup systemGroup = systemGroups.get(0);
+
+        // cancel
+        systemGroup.setAttributesStatusProcessed(Status.CANCELLED, when, username, structureElement.getComment());
+        systemGroupRepository.updateSystemGroup(systemGroup);
+
+        // previous
+        List<SystemGroup> previouses = iSystemGroupRepository.findPreviousByUuidAndId(uuid, systemGroup.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, systemGroup);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(systemGroup, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.SYSTEMGROUP, structureCommandCUD, StructureCommand.CANCEL,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, systemGroup, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification rejectStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     reject - update structure to status REJECTED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<SystemGroup> systemGroups = systemGroupRepository.readSystemGroups(Status.PENDING, null, uuid, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(systemGroups, 1)) {
+            return null;
+        }
+        SystemGroup systemGroup = systemGroups.get(0);
+
+        // reject
+        systemGroup.setAttributesStatusProcessed(Status.REJECTED, when, username, structureElement.getComment());
+        systemGroupRepository.updateSystemGroup(systemGroup);
+
+        // previous
+        List<SystemGroup> previouses = iSystemGroupRepository.findPreviousByUuidAndId(uuid, systemGroup.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, systemGroup);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(systemGroup, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.SYSTEMGROUP, structureCommandCUD, StructureCommand.REJECT,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, systemGroup, holder));
+    }
+
 }
diff --git a/src/main/java/org/openepics/names/service/SystemService.java b/src/main/java/org/openepics/names/service/SystemService.java
index 5033ed4d..b15aa75e 100644
--- a/src/main/java/org/openepics/names/service/SystemService.java
+++ b/src/main/java/org/openepics/names/service/SystemService.java
@@ -20,6 +20,7 @@ package org.openepics.names.service;
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -34,6 +35,7 @@ import org.openepics.names.rest.beans.Type;
 import org.openepics.names.rest.beans.element.NameElement;
 import org.openepics.names.rest.beans.element.NameElementCommand;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
+import org.openepics.names.util.EssNamingConvention;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
 import org.openepics.names.util.StructureCommand;
@@ -83,6 +85,71 @@ public class SystemService {
         this.subsystemService = subsystemService;
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification createStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        System system = new System(UUID.randomUUID(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        systemRepository.createSystem(system);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(system),
+                NotificationUtil.prepareNotification(Type.SYSTEM, StructureCommand.CREATE, null, null, system, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification updateStructure(StructureElementCommand structureElement, Date when, String username, EssNamingConvention namingConvention, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     create structure to pending, not latest, not deleted, with data
+        //     find out previous
+        //     return
+        //         structure element for updated structure
+        //         notification
+
+        // note
+        //     namingConvention.equivalenceClassRepresentative return null for null input
+        //     rules for mnemonic
+
+        String mnemonic = structureElement.getMnemonic();
+        mnemonic = StringUtils.isEmpty(mnemonic) ? null : mnemonic;
+        String equivalenceClassRepresentative = namingConvention.equivalenceClassRepresentative(mnemonic);
+
+        // create
+        System system = new System(structureElement.getUuid(), structureElement.getParent(),
+                structureElement.getName(), mnemonic, equivalenceClassRepresentative,
+                structureElement.getDescription(), Status.PENDING, Boolean.FALSE, Boolean.FALSE,
+                when, username, structureElement.getComment());
+        systemRepository.createSystem(system);
+
+        // previous
+        List<System> previouses = iSystemRepository.findPreviousByUuidAndId(system.getUuid().toString(),  system.getId());
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementRequested(system),
+                NotificationUtil.prepareNotification(Type.SYSTEM, StructureCommand.UPDATE, null,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, system, holder));
+    }
+
     @Transactional(propagation = Propagation.MANDATORY)
     public StructureElementNotification deleteStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
         // validation outside method
@@ -94,10 +161,8 @@ public class SystemService {
         //         structure element for deleted structure
         //         notification
 
-        String uuid = structureElement.getUuid().toString();
-
         // find
-        List<System> systems = systemRepository.readSystems(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
+        List<System> systems = systemRepository.readSystems(Status.APPROVED, Boolean.FALSE, structureElement.getUuid().toString(), null, null, null, null, null, null);
         if (ValidateUtil.isNullOrNotSize(systems, 1)) {
             return null;
         }
@@ -144,7 +209,6 @@ public class SystemService {
         //         notification
 
         String uuid = structureElement.getUuid().toString();
-        String comment = structureElement.getComment();
 
         // find
         List<System> systems = systemRepository.readSystems(Status.APPROVED, Boolean.FALSE, uuid, null, null, null, null, null, null);
@@ -165,7 +229,7 @@ public class SystemService {
         system = systems.get(0);
 
         // approve
-        system.setAttributesStatusProcessed(Status.APPROVED, when, username, comment);
+        system.setAttributesStatusProcessed(Status.APPROVED, when, username, structureElement.getComment());
         system.setLatest(Boolean.TRUE);
         systemRepository.updateSystem(system);
 
@@ -208,4 +272,74 @@ public class SystemService {
                 NotificationUtil.prepareNotification(Type.SYSTEM, structureCommandCUD, StructureCommand.APPROVE, previous, system, holder));
     }
 
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification cancelStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     cancel - update structure to status CANCELLED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<System> systems = systemRepository.readSystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(systems, 1)) {
+            return null;
+        }
+        System system = systems.get(0);
+
+        // cancel
+        system.setAttributesStatusProcessed(Status.CANCELLED, when, username, structureElement.getComment());
+        systemRepository.updateSystem(system);
+
+        // previous
+        List<System> previouses = iSystemRepository.findPreviousByUuidAndId(uuid, system.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, system);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(system, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.SYSTEM, structureCommandCUD, StructureCommand.CANCEL,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, system, holder));
+    }
+
+    @Transactional(propagation = Propagation.MANDATORY)
+    public StructureElementNotification rejectStructure(StructureElementCommand structureElement, Date when, String username, HolderSystemDeviceStructure holder) {
+        // validation outside method
+        // transaction
+        //     support a current transaction, throw an exception if none exists
+        //     find
+        //     reject - update structure to status REJECTED
+        //     find out previous
+        //     return
+        //         structure element for created structure
+        //         notification
+
+        String uuid = structureElement.getUuid().toString();
+
+        // find
+        List<System> systems = systemRepository.readSystems(Status.PENDING, null, uuid, null, null, null, null, null, null);
+        if (ValidateUtil.isNullOrNotSize(systems, 1)) {
+            return null;
+        }
+        System system = systems.get(0);
+
+        // reject
+        system.setAttributesStatusProcessed(Status.REJECTED, when, username, structureElement.getComment());
+        systemRepository.updateSystem(system);
+
+        // previous
+        List<System> previouses = iSystemRepository.findPreviousByUuidAndId(uuid, system.getId());
+        StructureCommand structureCommandCUD = NotificationUtil.getStructureCommandCUD(previouses, system);
+
+        return new StructureElementNotification(
+                StructureElementUtil.getStructureElementProcessed(system, holder, StructureChoice.STRUCTURE),
+                NotificationUtil.prepareNotification(Type.SYSTEM, structureCommandCUD, StructureCommand.REJECT,
+                        previouses != null && !previouses.isEmpty() ? previouses.get(0) : null, system, holder));
+    }
+
 }
-- 
GitLab