From 7366f8983bca5ce6e984795405f5baa6747be719 Mon Sep 17 00:00:00 2001
From: Joze RIHTARSIC <joze.rihtarsic@ext.ec.europa.eu>
Date: Mon, 29 Oct 2018 13:10:09 +0100
Subject: [PATCH] - small bugfixes

---
 smp-angular/src/app/app.component.ts          | 22 -----
 .../domain-details-dialog.component.ts        |  2 +-
 smp-angular/src/app/login/login.component.ts  |  4 +
 .../service-extension-edit-ro.model.ts        |  6 --
 ...ervice-group-details-dialog.component.html | 11 ++-
 .../service-group-details-dialog.component.ts | 51 +++++-----
 .../service-group-validation-edit-ro.model.ts | 10 ++
 ...rvice-group-validation-error-code.model.ts |  5 +
 ...rvice-group-metadata-dialog.component.html | 32 +++---
 ...service-group-metadata-dialog.component.ts |  5 +-
 ...rvice-metadata-validation-edit-ro.model.ts |  1 +
 ...vice-metadata-wizard-dialog.component.html |  6 +-
 ...ervice-metadata-wizard-dialog.component.ts |  2 +-
 .../service-metadata-wizard-edit-ro.model.ts  |  2 +-
 .../user-details-dialog.component.html        | 13 +--
 .../user-details-dialog.component.ts          | 27 +++--
 .../ec/edelivery/smp/data/dao/UserDao.java    |  6 +-
 .../smp/data/ui/ServiceGroupExtensionRO.java  | 32 ------
 .../smp/data/ui/ServiceGroupValidationRO.java | 74 ++++++++++++++
 .../data/ui/ServiceMetadataValidationRO.java  | 10 ++
 .../edelivery/smp/logging/SMPMessageCode.java |  4 +-
 .../services/ui/UIServiceGroupService.java    | 57 ++++++++---
 .../services/ui/UIServiceMetadataService.java | 99 ++++++++++++-------
 .../UIServiceGroupServiceIntegrationTest.java | 30 +++---
 .../edelivery/smp/testutil/TestROUtils.java   | 16 +--
 .../smp/ui/ServiceGroupResource.java          | 17 +---
 26 files changed, 322 insertions(+), 222 deletions(-)
 delete mode 100644 smp-angular/src/app/service-group-edit/service-group-details-dialog/service-extension-edit-ro.model.ts
 create mode 100644 smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-edit-ro.model.ts
 create mode 100644 smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-error-code.model.ts
 delete mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupExtensionRO.java
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupValidationRO.java

diff --git a/smp-angular/src/app/app.component.ts b/smp-angular/src/app/app.component.ts
index 13e5676e3..7f658c094 100644
--- a/smp-angular/src/app/app.component.ts
+++ b/smp-angular/src/app/app.component.ts
@@ -26,32 +26,10 @@ export class AppComponent implements OnInit {
               private securityEventService: SecurityEventService,
               private http: HttpClient,
               private titleService: Title) {
-/*
-    let applicationNameResponse: Observable<string> = this.http.get<string>('rest/application/name');
 
-    applicationNameResponse.subscribe((name: string) => {
-      this.titleService.setTitle(name);
-    });
-    */
   }
 
   ngOnInit() {
-    /*
-    this.securityEventService.onLoginSuccessEvent().subscribe(
-      data => {
-        this.isAdmin = this.securityService.isCurrentUserAdmin();
-      });
-
-    this.securityEventService.onLoginErrorEvent().subscribe(
-      error => {
-        this.isAdmin = this.securityService.isCurrentUserAdmin();
-      });
-
-    this.securityEventService.onLogoutSuccessEvent().subscribe(
-      data => {
-        this.isAdmin = this.securityService.isCurrentUserAdmin();
-        this.router.navigate(['/login']);
-      });*/
   }
 
   isCurrentUserSystemAdmin(): boolean {
diff --git a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts
index 6db5b2d33..4e3376f62 100644
--- a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts
+++ b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts
@@ -145,7 +145,7 @@ export class DomainDetailsDialogComponent {
               'smlClientCertHeader': res.blueCoatHeader
             });
           } else {
-            this.alertService.exception("Error occurred while reading certificate.", "Check if uploaded file has valid certificate type?", false);
+            this.alertService.exception("Error occurred while reading certificate.", "Check if uploaded file has valid certificate type.", false);
           }
         },
         err => {
diff --git a/smp-angular/src/app/login/login.component.ts b/smp-angular/src/app/login/login.component.ts
index 8115e16b8..b76c44a36 100644
--- a/smp-angular/src/app/login/login.component.ts
+++ b/smp-angular/src/app/login/login.component.ts
@@ -69,6 +69,8 @@ export class LoginComponent implements OnInit, OnDestroy {
                 break;
               default:
                 message = "The username/password combination you provided are not valid. Please try again or contact your administrator.";
+                // clear the password
+                this.model.password='';
                 break;
             }
             break;
@@ -85,6 +87,8 @@ export class LoginComponent implements OnInit, OnDestroy {
   }
 
   login() {
+    // clear alerts
+    this.alertService.clearAlert();
     this.securityService.login(this.model.username, this.model.password);
   }
 
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-extension-edit-ro.model.ts b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-extension-edit-ro.model.ts
deleted file mode 100644
index 9c2d25b7d..000000000
--- a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-extension-edit-ro.model.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-
-export interface ServiceGroupExtensionRo  {
-  serviceGroupId: number;
-  extension: string;
-  errorMessage?: string;
-}
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
index 22b512404..833229722 100644
--- a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
+++ b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
@@ -17,6 +17,11 @@
               style="color:red; font-size: 70%">
               Participant identifier must not be empty.
             </div>
+            <div
+              *ngIf="(!editMode &&  dialogForm.controls['participantIdentifier'].hasError('dbExist'))"
+              style="color:red; font-size: 70%">
+              Participant identifier for given scheme is already defined in database!
+            </div>
           </mat-form-field>
 
           <mat-form-field style="width:100%">
@@ -119,7 +124,7 @@
               <span>Extension wizard</span>
             </button>
             <button mat-raised-button color="primary"
-                    atTooltip="Validate extension by XSD schema."
+                    atTooltip="Validate extension by XSD scheme."
                     matTooltipPosition="below"
                     (click)="onExtensionValidate()">
               <mat-icon>warning</mat-icon>
@@ -150,11 +155,7 @@
             [style.color]="isExtensionValid?'green':'red'">
             {{extensionValidationMessage}}
           </div>
-
         </div>
-
-
-
         <!-- mat-form-field>
           <div>
           <textarea style="width:100% !important;height: 400px !important;  -webkit-box-sizing: border-box;
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
index 448afe18b..91b69c100 100644
--- a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
+++ b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
@@ -9,12 +9,13 @@ import {SearchTableEntityStatus} from "../../common/search-table/search-table-en
 import {ServiceGroupEditRo} from "../service-group-edit-ro.model";
 import {GlobalLookups} from "../../common/global-lookups";
 import {ServiceGroupExtensionWizardDialogComponent} from "../service-group-extension-wizard-dialog/service-group-extension-wizard-dialog.component";
-import {ServiceGroupExtensionRo} from "./service-extension-edit-ro.model";
+import {ServiceGroupValidationRo} from "./service-group-validation-edit-ro.model";
 import {DomainRo} from "../../domain/domain-ro.model";
 import {ServiceGroupDomainEditRo} from "../service-group-domain-edit-ro.model";
 import {ConfirmationDialogComponent} from "../../common/confirmation-dialog/confirmation-dialog.component";
 import {SecurityService} from "../../security/security.service";
 import {UserRo} from "../../user/user-ro.model";
+import {ServiceGroupValidationErrorCodeModel} from "./service-group-validation-error-code.model";
 
 @Component({
   selector: 'service-group-details',
@@ -34,7 +35,7 @@ export class ServiceGroupDetailsDialogComponent implements OnInit {
   showSpinner: boolean = false;
 
   dialogForm: FormGroup;
-  extensionObserver: Observable<ServiceGroupExtensionRo>;
+  extensionObserver: Observable<ServiceGroupValidationRo>;
 
   extensionValidationMessage: String = null;
   isExtensionValid: boolean = true;
@@ -90,7 +91,7 @@ export class ServiceGroupDetailsDialogComponent implements OnInit {
         this.current.status !== SearchTableEntityStatus.NEW ? Validators.required : null),
       'serviceGroupDomains': new FormControl({value: []}, [this.minSelectedListCount(1)]),
       'users': new FormControl({value: []}, [this.minSelectedListCount(1)]),
-      'extension': new FormControl({value: []}, []),
+      'extension': new FormControl({value: ''}, []),
 
 
     });
@@ -107,8 +108,8 @@ export class ServiceGroupDetailsDialogComponent implements OnInit {
     // retrieve xml extension for this service group
     if (this.current.status !== SearchTableEntityStatus.NEW && !this.current.extension) {
       // init domains
-      this.extensionObserver = this.http.get<ServiceGroupExtensionRo>(SmpConstants.REST_SERVICE_GROUP_EXTENSION + '/' + this.current.id);
-      this.extensionObserver.subscribe((res: ServiceGroupExtensionRo) => {
+      this.extensionObserver = this.http.get<ServiceGroupValidationRo>(SmpConstants.REST_SERVICE_GROUP_EXTENSION + '/' + this.current.id);
+      this.extensionObserver.subscribe((res: ServiceGroupValidationRo) => {
         this.dialogForm.get('extension').setValue(res.extension);
       });
     }
@@ -125,18 +126,26 @@ export class ServiceGroupDetailsDialogComponent implements OnInit {
     this.checkValidity(this.dialogForm);
 
 
-    let request: ServiceGroupExtensionRo = {
+    let request: ServiceGroupValidationRo = {
       serviceGroupId: this.current.id,
+      participantScheme: this.dialogForm.controls['participantScheme'].value,
+      participantIdentifier: this.dialogForm.controls['participantIdentifier'].value,
       extension: this.dialogForm.controls['extension'].value,
+      statusAction: this.editMode?SearchTableEntityStatus.UPDATED:SearchTableEntityStatus.NEW,
     }
     //
-    let validationObservable = this.http.post<ServiceGroupExtensionRo>(SmpConstants.REST_SERVICE_GROUP_EXTENSION_VALIDATE, request);
+    let validationObservable = this.http.post<ServiceGroupValidationRo>(SmpConstants.REST_SERVICE_GROUP_EXTENSION_VALIDATE, request);
     this.showSpinner = true;
-    validationObservable.toPromise().then((res: ServiceGroupExtensionRo) => {
+    validationObservable.toPromise().then((res: ServiceGroupValidationRo) => {
       if (res.errorMessage) {
-        this.extensionValidationMessage = res.errorMessage;
+
         this.isExtensionValid = false;
         this.showSpinner = false;
+        if (res.errorCode == ServiceGroupValidationErrorCodeModel.ERROR_CODE_SERVICE_GROUP_EXISTS){
+          this.dialogForm.controls['participantIdentifier'].setErrors({'dbExist': true});
+        } else {
+          this.extensionValidationMessage = res.errorMessage;
+        }
       } else {
         this.extensionValidationMessage = "Extension is valid!";
         this.isExtensionValid = true;
@@ -237,14 +246,17 @@ export class ServiceGroupDetailsDialogComponent implements OnInit {
 
   public onExtensionValidate() {
 
-    let request: ServiceGroupExtensionRo = {
+    let request: ServiceGroupValidationRo = {
       serviceGroupId: this.current.id,
+      participantScheme: this.dialogForm.controls['participantScheme'].value,
+      participantIdentifier: this.dialogForm.controls['participantIdentifier'].value,
       extension: this.dialogForm.controls['extension'].value,
+      statusAction: SearchTableEntityStatus.UPDATED, // do not validate as new  - for new participant id and schema is also validated
     }
     //
-    let validationObservable = this.http.post<ServiceGroupExtensionRo>(SmpConstants.REST_SERVICE_GROUP_EXTENSION_VALIDATE, request);
+    let validationObservable = this.http.post<ServiceGroupValidationRo>(SmpConstants.REST_SERVICE_GROUP_EXTENSION_VALIDATE, request);
     this.showSpinner = true;
-    validationObservable.toPromise().then((res: ServiceGroupExtensionRo) => {
+    validationObservable.toPromise().then((res: ServiceGroupValidationRo) => {
       if (res.errorMessage) {
         this.extensionValidationMessage = res.errorMessage;
         this.isExtensionValid = false;
@@ -259,22 +271,7 @@ export class ServiceGroupDetailsDialogComponent implements OnInit {
   }
 
   onPrettyPrintExtension() {
-    let existingXML = this.dialogForm.controls['extension'].value;
-    let request: ServiceGroupExtensionRo = {
-      serviceGroupId: this.current.id,
-      extension: existingXML,
-    }
-    let validationObservable = this.http.post<ServiceGroupExtensionRo>(SmpConstants.REST_SERVICE_GROUP_EXTENSION_FORMAT, request);
-    validationObservable.subscribe((res: ServiceGroupExtensionRo) => {
-      if (res.errorMessage) {
-        this.extensionValidationMessage = res.errorMessage;
-        this.isExtensionValid = false;
-      } else {
-        this.dialogForm.get('extension').setValue(res.extension);
-        this.isExtensionValid = true;
-      }
 
-    });
   }
 
   onDomainSelectionChanged(event) {
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-edit-ro.model.ts b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-edit-ro.model.ts
new file mode 100644
index 000000000..ad2d6f161
--- /dev/null
+++ b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-edit-ro.model.ts
@@ -0,0 +1,10 @@
+
+export interface ServiceGroupValidationRo  {
+  serviceGroupId: number;
+  participantScheme: string;
+  participantIdentifier: string;
+  extension: string;
+  errorMessage?: string;
+  statusAction:number;
+  errorCode?: number;
+}
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-error-code.model.ts b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-error-code.model.ts
new file mode 100644
index 000000000..c1ed1858e
--- /dev/null
+++ b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-validation-error-code.model.ts
@@ -0,0 +1,5 @@
+export enum ServiceGroupValidationErrorCodeModel {
+  ERROR_CODE_OK,
+  ERROR_CODE_SERVICE_GROUP_EXISTS,
+  ERROR_CODE_INVALID_EXTENSION
+}
diff --git a/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.html b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.html
index db576dbfc..ca070b24d 100644
--- a/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.html
+++ b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.html
@@ -6,7 +6,7 @@
       <mat-card-content >
         <div class="panel">
           <mat-form-field  style="width:30%">
-            <input matInput placeholder="Participant schema" name="patricipantSchema"  id="participanSchema_id"
+            <input matInput placeholder="Participant scheme" name="patricipantSchema"  id="participanSchema_id"
                    [formControl]="dialogForm.controls['participantScheme']"
             >
           </mat-form-field>
@@ -28,11 +28,11 @@
 
           <mat-form-field  style="width:30%">
             <input matInput placeholder="Document identifier scheme" name="documentScheme"  id="documentScheme_id"
-                   [formControl]="dialogForm.controls['documentIdentifierScheme']">
+                   [formControl]="dialogForm.controls['documentIdentifierScheme']"  maxlength="255" required>
           </mat-form-field>
             <mat-form-field style="width:55%">
               <input matInput placeholder="Document identifier" name="documentIdentifier"  id="documentIdentifier_id"
-                     [formControl]="dialogForm.controls['documentIdentifier']">
+                     [formControl]="dialogForm.controls['documentIdentifier']"  maxlength="255" required>
             </mat-form-field>
         </div>
       </mat-card-content>
@@ -74,37 +74,29 @@
           </mat-toolbar-row>
         </mat-toolbar>
 
-        <div style="display: block;" style="border:1px; solid: #999999;margin:5px 0; padding:3px;">
+        <div style="display: block;border:1px; solid: #999999;margin:5px 0; padding:3px;">
           <div class="textwrapper">
             <textarea matInput style="width:100%;border: #03A9F4 1px solid" cols="2" rows="25"
                       resizeable="false"
                       id="MetadataTextArea"
-                      placeholder="Metadata XML" name="metadataXML"
+                      placeholder="Metadata XML*" name="metadataXML"
                       [formControl]="dialogForm.controls['xmlContent']"
 
-            ></textarea>
+                      required></textarea>
           </div>
           <div
-            *ngIf="metadataValidationMessage"
+            *ngIf="(!editMode && dialogForm.controls['xmlContent'].dirty || editMode) &&  dialogForm.controls['xmlContent'].hasError('required')"
+            style="color:red; font-size: 70%">
+            Valid service metadata XML is required!
+          </div>
+          <div
+            *ngIf="metadataValidationMessage && !((!editMode && dialogForm.controls['xmlContent'].touched || editMode) &&  dialogForm.controls['xmlContent'].hasError('required'))"
             [style.color]="isMetadataValid?'green':'red'">
             {{metadataValidationMessage}}
           </div>
 
         </div>
 
-
-        <!-- mat-form-field>
-          <div>
-          <textarea style="width:100% !important;height: 400px !important;  -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-            box-sizing: border-box;"
-
-                    matInput id="extensionTextArea"
-                    placeholder="Extension" name="extension"
-                    [formControl]="dialogForm.controls['extension']"
-          ></textarea>
-    </div>
-        </mat-form-field -->
       </mat-card-content>
     </mat-card>
   </div>
diff --git a/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.ts
index c688e7d4f..93a0ae4dc 100644
--- a/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.ts
+++ b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.ts
@@ -73,7 +73,7 @@ export class ServiceGroupMetadataDialogComponent implements OnInit {
           disabled: this.editMode
         },
         [Validators.required]),
-      'xmlContent': new FormControl({value: []}, []),
+      'xmlContent': new FormControl({value: ''}, [Validators.required]),
     });
 
     // update values
@@ -123,6 +123,7 @@ export class ServiceGroupMetadataDialogComponent implements OnInit {
       documentIdentifierScheme: this.dialogForm.controls['documentIdentifierScheme'].value,
       documentIdentifier: this.dialogForm.controls['documentIdentifier'].value,
       xmlContent: this.dialogForm.controls['xmlContent'].value,
+      statusAction: this.editMode?SearchTableEntityStatus.UPDATED:SearchTableEntityStatus.NEW,
     }
     //
     let validationObservable = this.http.post<ServiceMetadataValidationEditRo>(SmpConstants.REST_METADATA_VALIDATE, request);
@@ -191,11 +192,13 @@ export class ServiceGroupMetadataDialogComponent implements OnInit {
   onServiceMetadataValidate() {
 
     let request: ServiceMetadataValidationEditRo = {
+
       participantScheme: this.dialogForm.controls['participantScheme'].value,
       participantIdentifier: this.dialogForm.controls['participantIdentifier'].value,
       documentIdentifierScheme: this.dialogForm.controls['documentIdentifierScheme'].value,
       documentIdentifier: this.dialogForm.controls['documentIdentifier'].value,
       xmlContent: this.dialogForm.controls['xmlContent'].value,
+      statusAction: this.editMode?SearchTableEntityStatus.UPDATED:SearchTableEntityStatus.NEW,
     }
     //
     let validationObservable = this.http.post<ServiceMetadataValidationEditRo>(SmpConstants.REST_METADATA_VALIDATE, request);
diff --git a/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-metadata-validation-edit-ro.model.ts b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-metadata-validation-edit-ro.model.ts
index f6efa05dc..3f5fb4223 100644
--- a/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-metadata-validation-edit-ro.model.ts
+++ b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-metadata-validation-edit-ro.model.ts
@@ -7,4 +7,5 @@ export interface ServiceMetadataValidationEditRo {
 
   errorMessage?: string;
   xmlContent?: string;
+  statusAction: number;
 }
diff --git a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.html b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.html
index e9fa2cd3a..73ca478df 100644
--- a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.html
+++ b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.html
@@ -7,7 +7,7 @@
         <div class="panel">
           <!-- Participant -->
           <mat-form-field style="width:35%">
-            <input matInput placeholder="Participant identifier schema" name="participantIdentifierScheme"
+            <input matInput placeholder="Participant identifier scheme" name="participantIdentifierScheme"
                    id="participantIdentifierScheme_id" maxlength="255">
           </mat-form-field>
           <mat-form-field style="width:60%">
@@ -21,7 +21,7 @@
           </mat-form-field>
           <!-- Document -->
           <mat-form-field style="width:35%">
-            <input matInput placeholder="Document identifier schema" name="documentIdentifierScheme"
+            <input matInput placeholder="Document identifier scheme" name="documentIdentifierScheme"
                    id="documentIdentifierScheme_id"
                    maxlength="255">
           </mat-form-field>
@@ -32,7 +32,7 @@
           </mat-form-field>
           <!-- Process -->
           <mat-form-field style="width:35%">
-            <input matInput placeholder="Process schema" name="processSchema" id="processSchema_id"
+            <input matInput placeholder="Process scheme" name="processSchema" id="processSchema_id"
                    maxlength="255" required>
           </mat-form-field>
 
diff --git a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts
index 9e9dfecc8..c52d10d66 100644
--- a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts
+++ b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts
@@ -35,7 +35,7 @@ export class ServiceMetadataWizardDialogComponent {
 
       'documentIdentifier': new FormControl({value: ''}, [Validators.required]),
       'documentIdentifierScheme': new FormControl({value: ''}, null),
-      'processSchema': new FormControl({value: ''}, [Validators.required]),
+      'processScheme': new FormControl({value: ''}, [Validators.required]),
       'processIdentifier': new FormControl({value: ''}, [Validators.required]),
       'endpointUrl': new FormControl({value: ''}, [Validators.required]),
       'endpointCertificate': new FormControl({value: ''}, null),
diff --git a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-edit-ro.model.ts b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-edit-ro.model.ts
index abc19b6b0..94cd2150e 100644
--- a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-edit-ro.model.ts
+++ b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-edit-ro.model.ts
@@ -4,7 +4,7 @@ export interface ServiceMetadataWizardRo  {
   participantIdentifier: string;
   documentIdentifierScheme: string;
   documentIdentifier: string;
-  processSchema: string;
+  processScheme: string;
   processIdentifier: string;
   transportProfile: string;
   endpointUrl: string;
diff --git a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.html b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.html
index dee9d6251..42519b1ac 100644
--- a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.html
+++ b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.html
@@ -103,11 +103,11 @@
         </mat-slide-toggle>
         <div
           *ngIf="userForm.errors?.userDetailsOrCertificateRequired && (userForm.get('userToggle').dirty || userForm.get('certificateToggle').dirty)"
-          class="has-error">You need to enter at least the details or the certificate for this user
-        </div>
-        <div *ngIf="userForm.errors?.certificateDetailsRequired && userForm.get('certificateToggle').touched"
-             class="has-error">All the certificate fields are required so please upload a new certificate
-        </div>
+          class="has-error">You need to enter at least the details or the certificate for this user!</div>
+        <div *ngIf="userForm.errors?.certificatedetailsrequired && userForm.get('certificateToggle').touched"
+             class="has-error">All the certificate fields are required so please upload a new certificate!</div>
+        <div *ngIf="userForm.errors?.certificateIdExists"
+             class="has-error">Certificate is already used by another user!</div>
       </mat-card-title>
       <mat-card-content>
         <div class="panel">
@@ -129,7 +129,8 @@
           </mat-form-field>
           <mat-form-field style="width: 100%;">
             <input matInput placeholder="SMP certificate ID" [formControl]="userForm.controls['certificateId']"
-                   id="certificateId_id">
+                   id="certificateId_id"
+                  resizeable="true">
           </mat-form-field>
 
           <label class="custom-file-upload">
diff --git a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
index b3996d85a..8a4dd23ee 100644
--- a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
+++ b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
@@ -74,9 +74,19 @@ export class UserDetailsDialogComponent {
         && certificateToggle.value && !(subject.value && validFrom.value && validTo.value && issuer.value && serialNumber.value) ? { certificateDetailsRequired: true} : null;
   };
 
+  private certificateExistValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
+    const certificateToggle = control.get('certificateToggle');
+    const certificateId = control.get('certificateId');
+    // get all persisted
+    const listIds = this.lookups.cachedServiceGroupOwnerList.map(a => a.certificate?a.certificate.certificateId:"NoId");
+
+    return certificateToggle && certificateId && certificateId.value
+    &&  listIds.includes(certificateId.value) &&  this.current.certificate && certificateId.value !== this.current.certificate.certificateId ? { certificateIdExists: true} : null;
+  };
+
   notInList(list: string[]) {
     return (c: AbstractControl): { [key: string]: any } => {
-      if (c.value && list.includes(c.value))
+      if (c.value && list.includes(c.value.toString().toLowerCase()))
         return {'notInList': {valid: false}};
 
       return null;
@@ -132,8 +142,8 @@ export class UserDetailsDialogComponent {
       'passwordToggle': new FormControl({value: bSetPassword, disabled:!bUserPasswordAuthentication}),
       'username': new FormControl({ value: '', disabled: this.editMode || !bUserPasswordAuthentication },
         !this.editMode || !this.current.username ? [Validators.nullValidator, Validators.pattern(this.usernamePattern),
-          this.notInList(this.lookups.cachedServiceGroupOwnerList.map(a => a.username))] : null),
-      // improve notInList validator
+          this.notInList(this.lookups.cachedServiceGroupOwnerList.map(a => a.username?a.username.toLowerCase():null))] : null),
+      //       // improve notInList validator
       'password': new FormControl({ value: '', disabled: !bUserPasswordAuthentication || !bSetPassword},
         [Validators.required, Validators.pattern(this.passwordPattern)]),
       'confirmation': new FormControl({ value: '', disabled: !bUserPasswordAuthentication  || !bSetPassword},
@@ -145,9 +155,14 @@ export class UserDetailsDialogComponent {
       'validTo': new FormControl({ value: '', disabled: true }, Validators.required),
       'issuer': new FormControl({ value: '', disabled: true }, Validators.required),
       'serialNumber': new FormControl({ value: '', disabled: true }, Validators.required),
-      'certificateId': new FormControl({ value: '', disabled: true }, Validators.required),
+      'certificateId': new FormControl({ value: '', disabled: true,  }, [Validators.required]
+       ),
     }, {
-      validator: [this.passwordConfirmationValidator, this.atLeastOneToggleCheckedValidator, this.certificateValidator]
+      validator: [this.passwordConfirmationValidator,
+        this.atLeastOneToggleCheckedValidator,
+        this.certificateValidator,
+        this.certificateExistValidator,
+        ]
     });
     // bind values to form! not property
     this.userForm.controls['active'].setValue(this.current.active);
@@ -205,7 +220,7 @@ export class UserDetailsDialogComponent {
                 'certificateId': res.certificateId
               });
             } else {
-              this.alertService.exception("Error occurred while reading certificate.", "Check if uploaded file has valid certificate type?", false);
+              this.alertService.exception("Error occurred while reading certificate.", "Check if uploaded file has valid certificate type.", false);
             }
           },
           err => {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
index 95322f3df..e4d8e98ba 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
@@ -39,7 +39,7 @@ public class UserDao extends BaseDao<DBUser> {
 
 
     /**
-     * Perstis user to database. Before that test if user has identifiers
+     * Persis user to database. Before that test if user has identifiers. Usernames are saved to database in lower caps
      * @param user
      */
     @Override
@@ -49,6 +49,10 @@ public class UserDao extends BaseDao<DBUser> {
                 && (user.getCertificate() == null || StringUtils.isBlank(user.getCertificate().getCertificateId() )) ) {
             throw new SMPRuntimeException(ErrorCode.INVALID_USER_NO_IDENTIFIERS);
         }
+        // update username to lower caps
+        if (!StringUtils.isBlank(user.getUsername())){
+            user.setUsername(user.getUsername().toLowerCase());
+        }
         super.persistFlushDetach(user);
     }
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupExtensionRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupExtensionRO.java
deleted file mode 100644
index 0fc54379c..000000000
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupExtensionRO.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package eu.europa.ec.edelivery.smp.data.ui;
-
-public class ServiceGroupExtensionRO extends BaseRO {
-    private static final long serialVersionUID = -7555221767041516157L;
-    Long serviceGroupId;
-    String extension;
-    String errorMessage;
-
-    public Long getServiceGroupId() {
-        return serviceGroupId;
-    }
-
-    public void setServiceGroupId(Long serviceGroupId) {
-        this.serviceGroupId = serviceGroupId;
-    }
-
-    public String getExtension() {
-        return extension;
-    }
-
-    public void setExtension(String extension) {
-        this.extension = extension;
-    }
-
-    public String getErrorMessage() {
-        return errorMessage;
-    }
-
-    public void setErrorMessage(String errorMessage) {
-        this.errorMessage = errorMessage;
-    }
-}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupValidationRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupValidationRO.java
new file mode 100644
index 000000000..ac351c569
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupValidationRO.java
@@ -0,0 +1,74 @@
+package eu.europa.ec.edelivery.smp.data.ui;
+
+public class ServiceGroupValidationRO extends BaseRO {
+    private static final long serialVersionUID = -7555221767041516157L;
+
+    public static int ERROR_CODE_OK =0;
+    public static int ERROR_CODE_SERVICE_GROUP_EXISTS =1;
+    public static int ERROR_CODE_INVALID_EXTENSION =2;
+
+    Long serviceGroupId;
+    String extension;
+    String errorMessage;
+    String participantScheme;
+    String participantIdentifier;
+    int statusAction = 0;
+
+    int errorCode = ERROR_CODE_OK;
+
+    public Long getServiceGroupId() {
+        return serviceGroupId;
+    }
+
+    public void setServiceGroupId(Long serviceGroupId) {
+        this.serviceGroupId = serviceGroupId;
+    }
+
+    public String getExtension() {
+        return extension;
+    }
+
+    public void setExtension(String extension) {
+        this.extension = extension;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
+    public int getStatusAction() {
+        return statusAction;
+    }
+
+    public void setStatusAction(int statusAction) {
+        this.statusAction = statusAction;
+    }
+
+    public String getParticipantScheme() {
+        return participantScheme;
+    }
+
+    public void setParticipantScheme(String participantScheme) {
+        this.participantScheme = participantScheme;
+    }
+
+    public String getParticipantIdentifier() {
+        return participantIdentifier;
+    }
+
+    public void setParticipantIdentifier(String participantIdentifier) {
+        this.participantIdentifier = participantIdentifier;
+    }
+
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    public void setErrorCode(int errorCode) {
+        this.errorCode = errorCode;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataValidationRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataValidationRO.java
index 37e7bc5ec..7f6ff6e17 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataValidationRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataValidationRO.java
@@ -17,6 +17,8 @@ public class ServiceMetadataValidationRO extends BaseRO {
     String errorMessage;
     String xmlContent;
 
+    int statusAction = 0;
+
     public String getParticipantScheme() {
         return participantScheme;
     }
@@ -64,4 +66,12 @@ public class ServiceMetadataValidationRO extends BaseRO {
     public void setXmlContent(String xmlContent) {
         this.xmlContent = xmlContent;
     }
+
+    public int getStatusAction() {
+        return statusAction;
+    }
+
+    public void setStatusAction(int statusAction) {
+        this.statusAction = statusAction;
+    }
 }
\ No newline at end of file
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java
index 7db631120..03caaef15 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java
@@ -27,8 +27,8 @@ public enum SMPMessageCode implements MessageCode {
     BUS_HTTP_GET_SERVICE_METADATA ("BUS-012", "Http GET ServiceGroup from host: {}, ServiceGroup id: {}, metadata id {}."),
     BUS_HTTP_GET_END_SERVICE_METADATA ("BUS-013", "End Http GET ServiceGroup from host: {}, ServiceGroup id: {}, metadata id {}."),
 
-    BUS_SAVE_SERVICE_GROUP ("BUS-014", "Start inserting/updating ServiceGroup for domain {}, part. Id: {} part. schema {}."),
-    BUS_SAVE_SERVICE_GROUP_FAILED ("BUS-015", "Inserting/updating ServiceGroup for domain {}, part. Id: {} part. schema {} failed! Error: [{}]"),
+    BUS_SAVE_SERVICE_GROUP ("BUS-014", "Start inserting/updating ServiceGroup for domain {}, part. Id: {} part. scheme {}."),
+    BUS_SAVE_SERVICE_GROUP_FAILED ("BUS-015", "Inserting/updating ServiceGroup for domain {}, part. Id: {} part. scheme {} failed! Error: [{}]"),
 
 
     BUS_INVALID_XML("BUS-030", "Invalid XML for {}. Error: [{}]"),
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
index e9ce987c2..beee7dafa 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
@@ -36,6 +36,9 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
+import static eu.europa.ec.edelivery.smp.data.ui.ServiceGroupValidationRO.ERROR_CODE_INVALID_EXTENSION;
+import static eu.europa.ec.edelivery.smp.data.ui.ServiceGroupValidationRO.ERROR_CODE_OK;
+import static eu.europa.ec.edelivery.smp.data.ui.ServiceGroupValidationRO.ERROR_CODE_SERVICE_GROUP_EXISTS;
 import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.*;
 
 @Service
@@ -109,8 +112,8 @@ public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, Service
     }
 
     @Transactional
-    public ServiceGroupExtensionRO getServiceGroupExtensionById(Long serviceGroupId) {
-        ServiceGroupExtensionRO ex = new ServiceGroupExtensionRO();
+    public ServiceGroupValidationRO getServiceGroupExtensionById(Long serviceGroupId) {
+        ServiceGroupValidationRO ex = new ServiceGroupValidationRO();
         DBServiceGroup dbServiceGroup = getDatabaseDao().find(serviceGroupId);
         ex.setServiceGroupId(dbServiceGroup.getId());
         if (dbServiceGroup.getExtension() != null) {
@@ -493,8 +496,9 @@ public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, Service
 
         byte[] buff = validateServiceMetadata(serviceMetadataRO);
         DBServiceMetadata dbServiceMetadata = new DBServiceMetadata();
-        dbServiceMetadata.setDocumentIdentifier(serviceMetadataRO.getDocumentIdentifier());
-        dbServiceMetadata.setDocumentIdentifierScheme(serviceMetadataRO.getDocumentIdentifierScheme());
+        DocumentIdentifier docIdent=  caseSensitivityNormalizer.normalizeDocumentIdentifier(serviceMetadataRO.getDocumentIdentifierScheme(),serviceMetadataRO.getDocumentIdentifier() );
+        dbServiceMetadata.setDocumentIdentifier(docIdent.getValue());
+        dbServiceMetadata.setDocumentIdentifierScheme(docIdent.getScheme());
         dbServiceMetadata.setXmlContent(buff);
 
         return dbServiceMetadata;
@@ -525,26 +529,47 @@ public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, Service
     /**
      * Validate if extension is valid by schema.
      *
-     * @param sgExtension
+     * @param serviceGroup
      * @return
      */
-    public ServiceGroupExtensionRO validateExtension(ServiceGroupExtensionRO sgExtension) {
-        if (sgExtension == null) {
+    public ServiceGroupValidationRO validateServiceGroup(ServiceGroupValidationRO serviceGroup) {
+
+        if (serviceGroup == null) {
             throw new SMPRuntimeException(INVALID_REQEUST, "Validate extension", "Missing Extension parameter");
-        } else if (StringUtils.isBlank(sgExtension.getExtension())) {
-            sgExtension.setErrorMessage("Empty extension");
+        } // if new check if service group already exist
+
+        if (serviceGroup.getStatusAction() == EntityROStatus.NEW.getStatusNumber()){
+            ParticipantIdentifierType headerPI = caseSensitivityNormalizer.normalizeParticipantIdentifier(
+                    serviceGroup.getParticipantScheme(),
+                    serviceGroup.getParticipantIdentifier());
+            Optional<DBServiceGroup> sg= serviceGroupDao.findServiceGroup(serviceGroup.getParticipantIdentifier(),
+                    serviceGroup.getParticipantScheme());
+            if (sg.isPresent()) {
+                serviceGroup.setErrorMessage("Service group: " +serviceGroup.getParticipantScheme()+ ":"+serviceGroup.getParticipantIdentifier()+
+                        " already exists!");
+                serviceGroup.setErrorCode(ERROR_CODE_SERVICE_GROUP_EXISTS);
+                return serviceGroup;
+            }
+        }
+
+        if (StringUtils.isBlank(serviceGroup.getExtension())) {
+            // emtpy extension is also a valid extension;
+            serviceGroup.setErrorMessage(null);
         } else {
             try {
-                byte[] buff = sgExtension.getExtension().getBytes("UTF-8");
+                byte[] buff = serviceGroup.getExtension().getBytes("UTF-8");
                 ExtensionConverter.validateExtensionBySchema(buff); // validate by schema
-                sgExtension.setErrorMessage(null);
+                serviceGroup.setErrorMessage(null);
+                serviceGroup.setErrorCode(ERROR_CODE_OK);
             } catch (XmlInvalidAgainstSchemaException e) {
-                sgExtension.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
+                serviceGroup.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
+                serviceGroup.setErrorCode(ERROR_CODE_INVALID_EXTENSION);
             } catch (UnsupportedEncodingException e) {
-                sgExtension.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
+                serviceGroup.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
+                serviceGroup.setErrorCode(ERROR_CODE_INVALID_EXTENSION);
             }
         }
-        return sgExtension;
+        return serviceGroup;
     }
 
     /**
@@ -568,12 +593,12 @@ public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, Service
     }
 
     /**
-     * TODO format extension - add root element and format...
+     * Method
      *
      * @param sgExtension
      * @return
      */
-    public ServiceGroupExtensionRO formatExtension(ServiceGroupExtensionRO sgExtension) {
+    public ServiceGroupValidationRO formatExtension(ServiceGroupValidationRO sgExtension) {
         if (sgExtension == null) {
             throw new SMPRuntimeException(INVALID_REQEUST, "Format extension", "Missing Extension parameter");
         } else if (StringUtils.isBlank(sgExtension.getExtension())) {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceMetadataService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceMetadataService.java
index 91f6cf4a8..620d1e731 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceMetadataService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceMetadataService.java
@@ -9,10 +9,13 @@ import eu.europa.ec.edelivery.smp.data.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.model.DBServiceMetadata;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceMetadataRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceMetadataValidationRO;
+import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.smp.api.exceptions.XmlInvalidAgainstSchemaException;
 import eu.europa.ec.smp.api.validators.BdxSmpOasisValidator;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.DocumentIdentifier;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.ParticipantIdentifierType;
@@ -22,6 +25,9 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.io.UnsupportedEncodingException;
+import java.util.Optional;
+
+import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.INVALID_REQEUST;
 
 @Service
 public class UIServiceMetadataService extends UIServiceBase<DBServiceMetadata, ServiceMetadataRO> {
@@ -67,43 +73,62 @@ public class UIServiceMetadataService extends UIServiceBase<DBServiceMetadata, S
 
     public ServiceMetadataValidationRO validateServiceMetadata(ServiceMetadataValidationRO serviceMetadataRO) {
         byte[] buff;
-
-        // convert to utf-8 byte array
-        try {
-            buff = serviceMetadataRO.getXmlContent().getBytes("UTF-8");
-            serviceMetadataRO.setXmlContent(""); // no need to return back schema
-        } catch (UnsupportedEncodingException e) {
-            serviceMetadataRO.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
-            serviceMetadataRO.setXmlContent(""); // no need to return back schema
-            return serviceMetadataRO;
-        }
-
-        // validate by schema
-        try {
-            BdxSmpOasisValidator.validateXSD(buff);
-        } catch (XmlInvalidAgainstSchemaException e) {
-            serviceMetadataRO.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
-            return serviceMetadataRO;
-        }
-
-        // validate data
-        ServiceMetadata smd = ServiceMetadataConverter.unmarshal(buff);
-        DocumentIdentifier xmlDI = caseSensitivityNormalizer.normalize(smd.getServiceInformation().getDocumentIdentifier());
-        DocumentIdentifier headerDI = caseSensitivityNormalizer.normalizeDocumentIdentifier(serviceMetadataRO.getDocumentIdentifierScheme(),
-                serviceMetadataRO.getDocumentIdentifier());
-        ParticipantIdentifierType xmlPI = caseSensitivityNormalizer.normalize(smd.getServiceInformation().getParticipantIdentifier());
-        ParticipantIdentifierType headerPI = caseSensitivityNormalizer.normalizeParticipantIdentifier(
-                serviceMetadataRO.getParticipantScheme(),
-                serviceMetadataRO.getParticipantIdentifier());
-
-        if (!xmlDI.equals(headerDI)) {
-            serviceMetadataRO.setErrorMessage("Document identifier and schema do not match!");
-            return serviceMetadataRO;
-        }
-
-        if (!xmlPI.equals(headerPI)) {
-            serviceMetadataRO.setErrorMessage("Participant identifier and schema do not match!");
-            return serviceMetadataRO;
+        if (serviceMetadataRO == null) {
+            throw new SMPRuntimeException(INVALID_REQEUST, "Validate service metadata", "Missing servicemetadata parameter");
+        } else if (StringUtils.isBlank(serviceMetadataRO.getXmlContent())) {
+            serviceMetadataRO.setErrorMessage("Service metadata xml must not be empty");
+        } else {
+
+
+            // validate xml  - first byte-array is expected to be in utf8 format
+            // convert to utf-8 byte array
+            try {
+                buff = serviceMetadataRO.getXmlContent().getBytes("UTF-8");
+                serviceMetadataRO.setXmlContent(""); // no need to return back schema
+            } catch (UnsupportedEncodingException e) {
+                serviceMetadataRO.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
+                serviceMetadataRO.setXmlContent(""); // no need to return back schema
+                return serviceMetadataRO;
+            }
+
+            // validate by schema
+            try {
+                BdxSmpOasisValidator.validateXSD(buff);
+            } catch (XmlInvalidAgainstSchemaException e) {
+                serviceMetadataRO.setErrorMessage(ExceptionUtils.getRootCauseMessage(e));
+                return serviceMetadataRO;
+            }
+
+            // validate data
+            ServiceMetadata smd = ServiceMetadataConverter.unmarshal(buff);
+            DocumentIdentifier xmlDI = caseSensitivityNormalizer.normalize(smd.getServiceInformation().getDocumentIdentifier());
+            DocumentIdentifier headerDI = caseSensitivityNormalizer.normalizeDocumentIdentifier(serviceMetadataRO.getDocumentIdentifierScheme(),
+                    serviceMetadataRO.getDocumentIdentifier());
+            ParticipantIdentifierType xmlPI = caseSensitivityNormalizer.normalize(smd.getServiceInformation().getParticipantIdentifier());
+            ParticipantIdentifierType headerPI = caseSensitivityNormalizer.normalizeParticipantIdentifier(
+                    serviceMetadataRO.getParticipantScheme(),
+                    serviceMetadataRO.getParticipantIdentifier());
+
+
+            if (serviceMetadataRO.getStatusAction() == EntityROStatus.NEW.getStatusNumber()){
+                // check if service metadata already exists
+                Optional<DBServiceMetadata> exists = serviceMetadataDao.findServiceMetadata(headerPI.getValue(), headerPI.getScheme(),
+                        headerDI.getValue(), headerDI.getScheme());
+                if (exists.isPresent()){
+                    serviceMetadataRO.setErrorMessage("Document identifier and scheme already exist in database!");
+                    return serviceMetadataRO;
+                }
+            }
+
+            if (!xmlDI.equals(headerDI)) {
+                serviceMetadataRO.setErrorMessage("Document identifier and scheme do not match!");
+                return serviceMetadataRO;
+            }
+
+            if (!xmlPI.equals(headerPI)) {
+                serviceMetadataRO.setErrorMessage("Participant identifier and scheme do not match!");
+                return serviceMetadataRO;
+            }
         }
 
         return serviceMetadataRO;
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java
index 6ee37dd0a..3748b7b88 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java
@@ -5,7 +5,7 @@ import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBServiceGroup;
 import eu.europa.ec.edelivery.smp.data.model.DBServiceMetadata;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
-import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupExtensionRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupValidationRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceMetadataRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
@@ -125,7 +125,7 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
         assertNotNull(res);
         assertEquals(1, res.getCount().intValue());
         ServiceGroupRO sgAdded = res.getServiceEntities().get(0);
-        ServiceGroupExtensionRO sgExt = testInstance.getServiceGroupExtensionById(sgAdded.getId());
+        ServiceGroupValidationRO sgExt = testInstance.getServiceGroupExtensionById(sgAdded.getId());
 
 
         // all table properties should not be null
@@ -179,7 +179,7 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
         assertNotNull(res);
         assertEquals(1, res.getCount().intValue());
         ServiceGroupRO sgUpdated = res.getServiceEntities().get(0);
-        ServiceGroupExtensionRO sgExt = testInstance.getServiceGroupExtensionById(sgUpdated.getId());
+        ServiceGroupValidationRO sgExt = testInstance.getServiceGroupExtensionById(sgUpdated.getId());
         assertEquals(1, sgChange.getServiceMetadata().size());
         // retrive service metadata xml with special service - it is not retrieve by browsing list
         ServiceMetadataRO smdXMLNew = uiServiceMetadataService.getServiceMetadataXMLById(sgUpdated.getServiceMetadata().get(0).getId());
@@ -242,10 +242,10 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
     @Test
     public void validateExtensionVaild() throws IOException {
         // given
-        ServiceGroupExtensionRO sg = TestROUtils.getValidExtension();
+        ServiceGroupValidationRO sg = TestROUtils.getValidExtension();
 
         // when
-        testInstance.validateExtension(sg);
+        testInstance.validateServiceGroup(sg);
 
         // then
         assertNull(sg.getErrorMessage());
@@ -255,10 +255,10 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
     @Test
     public void validateExtensionMultipleVaild() throws IOException {
         // given
-        ServiceGroupExtensionRO sg = TestROUtils.getValidMultipleExtension();
+        ServiceGroupValidationRO sg = TestROUtils.getValidMultipleExtension();
 
         // when
-        testInstance.validateExtension(sg);
+        testInstance.validateServiceGroup(sg);
 
         // then
         assertNull(sg.getErrorMessage());
@@ -268,10 +268,10 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
     @Test
     public void validateExtensionCustomTextInvaldValid() throws IOException {
         // given
-        ServiceGroupExtensionRO sg = TestROUtils.getValidCustomText();
+        ServiceGroupValidationRO sg = TestROUtils.getValidCustomText();
 
         // when
-        testInstance.validateExtension(sg);
+        testInstance.validateServiceGroup(sg);
 
         // then
         assertNotNull(sg.getErrorMessage());
@@ -281,10 +281,10 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
 
     @Test
     public void validateExtensionInvalid() throws IOException {
-        ServiceGroupExtensionRO sg = TestROUtils.getInvalid();
+        ServiceGroupValidationRO sg = TestROUtils.getInvalid();
 
         // when
-        testInstance.validateExtension(sg);
+        testInstance.validateServiceGroup(sg);
 
         // then
         assertNotNull(sg.getErrorMessage());
@@ -294,10 +294,10 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
 
     @Test
     public void validateCustomExtension() throws IOException {
-        ServiceGroupExtensionRO sg = TestROUtils.getCustomExtension();
+        ServiceGroupValidationRO sg = TestROUtils.getCustomExtension();
 
         // when
-        testInstance.validateExtension(sg);
+        testInstance.validateServiceGroup(sg);
 
         // then
         assertNull(sg.getErrorMessage());
@@ -313,7 +313,7 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
         assertNull(sg.getExtension());
 
         // when
-        ServiceGroupExtensionRO res = testInstance.getServiceGroupExtensionById(sg.getId());
+        ServiceGroupValidationRO res = testInstance.getServiceGroupExtensionById(sg.getId());
 
         // then
         assertNotNull(res);
@@ -328,7 +328,7 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
         assertNotNull(sg.getExtension());
 
         // when
-        ServiceGroupExtensionRO res = testInstance.getServiceGroupExtensionById(sg.getId());
+        ServiceGroupValidationRO res = testInstance.getServiceGroupExtensionById(sg.getId());
 
         // then
         assertNotNull(res);
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestROUtils.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestROUtils.java
index 2e318c107..7be76dde9 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestROUtils.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestROUtils.java
@@ -2,7 +2,7 @@ package eu.europa.ec.edelivery.smp.testutil;
 
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupDomainRO;
-import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupExtensionRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupValidationRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceMetadataRO;
 import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
@@ -74,35 +74,35 @@ public class TestROUtils {
         return String.format(SIMPLE_DOCUMENT_XML, partSch, partId,docSch, docId, UUID.randomUUID().toString()  );
     }
 
-    public static ServiceGroupExtensionRO getValidExtension() throws IOException {
+    public static ServiceGroupValidationRO getValidExtension() throws IOException {
         String inputDoc = XmlTestUtils.loadDocumentAsString(RES_PATH + "extensionValidOne.xml");
         return getExtensionRO(inputDoc);
     }
 
 
-    public static ServiceGroupExtensionRO getValidMultipleExtension() throws IOException {
+    public static ServiceGroupValidationRO getValidMultipleExtension() throws IOException {
         String inputDoc = XmlTestUtils.loadDocumentAsString(RES_PATH + "extensionValidMultiple.xml");
         return getExtensionRO(inputDoc);
     }
 
-    public static ServiceGroupExtensionRO getValidCustomText() throws IOException {
+    public static ServiceGroupValidationRO getValidCustomText() throws IOException {
         String inputDoc = XmlTestUtils.loadDocumentAsString(RES_PATH + "extensionCustomText.xml");
         return getExtensionRO(inputDoc);
     }
 
-    public static ServiceGroupExtensionRO getInvalid() throws IOException {
+    public static ServiceGroupValidationRO getInvalid() throws IOException {
         String inputDoc = XmlTestUtils.loadDocumentAsString(RES_PATH + "extensionInvalid.xml");
         return getExtensionRO(inputDoc);
     }
 
-    public static ServiceGroupExtensionRO getCustomExtension() throws IOException {
+    public static ServiceGroupValidationRO getCustomExtension() throws IOException {
         String inputDoc = XmlTestUtils.loadDocumentAsString(RES_PATH + "extensionCustom.xml");
         return getExtensionRO(inputDoc);
     }
 
 
-    public static ServiceGroupExtensionRO getExtensionRO(String extension) {
-        ServiceGroupExtensionRO sg = new ServiceGroupExtensionRO();
+    public static ServiceGroupValidationRO getExtensionRO(String extension) {
+        ServiceGroupValidationRO sg = new ServiceGroupValidationRO();
         sg.setServiceGroupId((long) 1);
         sg.setExtension(extension);
         return sg;
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
index 78357bf54..e2be0fba5 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
@@ -5,20 +5,16 @@ import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationToken;
 import eu.europa.ec.edelivery.smp.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.auth.SMPRole;
 import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
-import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
-import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupExtensionRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupValidationRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
-import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UIServiceGroupService;
 import eu.europa.ec.edelivery.smp.services.ui.filters.ServiceGroupFilter;
-import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.annotation.Secured;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.bind.annotation.*;
@@ -26,9 +22,6 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.PostConstruct;
 import javax.servlet.http.HttpServletRequest;
 import java.util.Arrays;
-import java.util.Optional;
-
-import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.DOMAIN_NOT_EXISTS;
 
 /**
  * @author Joze Rihtarsic
@@ -98,18 +91,18 @@ public class ServiceGroupResource {
     @PutMapping(produces = {"application/json"})
     @RequestMapping(method = RequestMethod.GET, path = "extension/{serviceGroupId}")
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SMP_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SERVICE_GROUP_ADMIN})
-    public ServiceGroupExtensionRO getExtensionServiceGroupById(@PathVariable Long serviceGroupId) {
+    public ServiceGroupValidationRO getExtensionServiceGroupById(@PathVariable Long serviceGroupId) {
         return uiServiceGroupService.getServiceGroupExtensionById(serviceGroupId);
     }
     @RequestMapping(path = "extension/validate", method = RequestMethod.POST)
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SMP_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SERVICE_GROUP_ADMIN})
-    public ServiceGroupExtensionRO getExtensionServiceGroupById(@RequestBody(required = true) ServiceGroupExtensionRO sg) {
-        return uiServiceGroupService.validateExtension(sg);
+    public ServiceGroupValidationRO getExtensionServiceGroupById(@RequestBody(required = true) ServiceGroupValidationRO sg) {
+        return uiServiceGroupService.validateServiceGroup(sg);
     }
 
     @RequestMapping(path = "extension/format", method = RequestMethod.POST)
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SMP_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SERVICE_GROUP_ADMIN})
-    public ServiceGroupExtensionRO formatExtension(@RequestBody(required = true) ServiceGroupExtensionRO sg) {
+    public ServiceGroupValidationRO formatExtension(@RequestBody(required = true) ServiceGroupValidationRO sg) {
         return uiServiceGroupService.formatExtension(sg);
     }
 
-- 
GitLab