Added support for showing typeless Policies

Policy types that has no json schema will be possible to
view and to delete. But not posible to create or to modify.

Change-Id: I0250dce8357b765f8c9c27963eddd3e9c466c1ef
Issue-ID: NONRTRIC-210
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/PolicyController.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/PolicyController.java
index 538030c..03d9d83 100644
--- a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/PolicyController.java
+++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/PolicyController.java
@@ -63,7 +63,7 @@
     // Endpoints
     public static final String VERSION_METHOD = ControlPanelConstants.VERSION_METHOD;
     public static final String POLICY_TYPES_METHOD = "policytypes";
-    public static final String POLICY_TYPE_ID_NAME = "policy_type_id";
+    public static final String POLICY_TYPE_PARAM = "type";
     public static final String POLICIES_NAME = "policies";
     public static final String POLICY_INSTANCE_ID_NAME = "policy_instance_id";
 
@@ -89,40 +89,42 @@
     }
 
     @ApiOperation(value = "Returns the policy instances for the given policy type.")
-    @GetMapping(POLICY_TYPES_METHOD + "/{" + POLICY_TYPE_ID_NAME + "}/" + POLICIES_NAME)
+    @GetMapping(POLICIES_NAME)
     @Secured({ControlPanelConstants.ROLE_ADMIN, ControlPanelConstants.ROLE_STANDARD})
-    public ResponseEntity<String> getPolicyInstances(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString) {
+    public ResponseEntity<String> getPolicyInstances(
+        @RequestParam(name = "type", required = true) String policyTypeIdString) {
         logger.debug("getPolicyInstances {}", policyTypeIdString);
         return this.policyAgentApi.getPolicyInstancesForType(policyTypeIdString);
     }
 
     @ApiOperation(value = "Returns a policy instance of a type")
-    @GetMapping(POLICY_TYPES_METHOD + "/{" + POLICY_TYPE_ID_NAME + "}/" + POLICIES_NAME + "/{" + POLICY_INSTANCE_ID_NAME
-        + "}")
+    @GetMapping(POLICIES_NAME + "/{" + POLICY_INSTANCE_ID_NAME + "}")
     @Secured({ControlPanelConstants.ROLE_ADMIN, ControlPanelConstants.ROLE_STANDARD})
-    public ResponseEntity<Object> getPolicyInstance(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString,
+    public ResponseEntity<Object> getPolicyInstance(
+        @RequestParam(name = "type", required = true) String policyTypeIdString,
         @PathVariable(POLICY_INSTANCE_ID_NAME) String policyInstanceId) {
         logger.debug("getPolicyInstance {}:{}", policyTypeIdString, policyInstanceId);
         return this.policyAgentApi.getPolicyInstance(policyInstanceId);
     }
 
     @ApiOperation(value = "Creates the policy instances for the given policy type.")
-    @PutMapping(POLICY_TYPES_METHOD + "/{" + POLICY_TYPE_ID_NAME + "}/" + POLICIES_NAME + "/{" + POLICY_INSTANCE_ID_NAME
-        + "}")
+    @PutMapping(POLICIES_NAME + "/{" + POLICY_INSTANCE_ID_NAME + "}")
     @Secured({ControlPanelConstants.ROLE_ADMIN})
-    public ResponseEntity<String> putPolicyInstance(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString,
-        @RequestParam(name = "ric", required = true) String ric,
-        @PathVariable(POLICY_INSTANCE_ID_NAME) String policyInstanceId, @RequestBody String instance) {
+    public ResponseEntity<String> putPolicyInstance( //
+        @RequestParam(POLICY_TYPE_PARAM) String policyTypeIdString, //
+        @RequestParam(name = "ric", required = true) String ric, //
+        @PathVariable(POLICY_INSTANCE_ID_NAME) String policyInstanceId, //
+        @RequestBody String instance) {
         logger.debug("putPolicyInstance ric: {}, typeId: {}, instanceId: {}, instance: {}", ric, policyTypeIdString,
             policyInstanceId, instance);
         return this.policyAgentApi.putPolicy(policyTypeIdString, policyInstanceId, instance, ric);
     }
 
     @ApiOperation(value = "Deletes the policy instances for the given policy type.")
-    @DeleteMapping(POLICY_TYPES_METHOD + "/{" + POLICY_TYPE_ID_NAME + "}/" + POLICIES_NAME + "/{"
-        + POLICY_INSTANCE_ID_NAME + "}")
+    @DeleteMapping(POLICIES_NAME + "/{" + POLICY_INSTANCE_ID_NAME + "}")
     @Secured({ControlPanelConstants.ROLE_ADMIN})
-    public ResponseEntity<String> deletePolicyInstance(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString,
+    public ResponseEntity<String> deletePolicyInstance( //
+        @RequestParam(POLICY_TYPE_PARAM) String policyTypeIdString,
         @PathVariable(POLICY_INSTANCE_ID_NAME) String policyInstanceId) {
         logger.debug("deletePolicyInstance typeId: {}, instanceId: {}", policyTypeIdString, policyInstanceId);
         return this.policyAgentApi.deletePolicy(policyInstanceId);
diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/policyagentapi/PolicyAgentApiImpl.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/policyagentapi/PolicyAgentApiImpl.java
index 20e72bb..613c801 100644
--- a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/policyagentapi/PolicyAgentApiImpl.java
+++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/policyagentapi/PolicyAgentApiImpl.java
@@ -75,6 +75,7 @@
 
     @Override
     public ResponseEntity<String> getAllPolicyTypes() {
+        final String TITLE = "title";
         try {
             final String url = "/policy_schemas";
             ResponseEntity<String> rsp = webClient.getForEntity(url).block();
@@ -83,18 +84,15 @@
             }
 
             PolicyTypes result = new PolicyTypes();
-
             JsonArray schemas = JsonParser.parseString(rsp.getBody()).getAsJsonArray();
             for (JsonElement schema : schemas) {
                 JsonObject schemaObj = schema.getAsJsonObject();
-                if (schemaObj.get("title") != null) {
-                    String title = schemaObj.get("title").getAsString();
-                    String schemaAsStr = schemaObj.toString();
-                    PolicyType pt = new PolicyType(title, schemaAsStr);
-                    result.add(pt);
-                } else {
-                    logger.warn("Ignoring schema: {}", schemaObj);
+                String title = "";
+                if (schemaObj.get(TITLE) != null) {
+                    title = schemaObj.get(TITLE).getAsString();
                 }
+                PolicyType pt = new PolicyType(title, schemaObj.toString());
+                result.add(pt);
             }
             return new ResponseEntity<>(gson.toJson(result), rsp.getStatusCode());
         } catch (Exception e) {
diff --git a/webapp-frontend/src/app/policy-control/policy-control.component.html b/webapp-frontend/src/app/policy-control/policy-control.component.html
index f185207..997defd 100644
--- a/webapp-frontend/src/app/policy-control/policy-control.component.html
+++ b/webapp-frontend/src/app/policy-control/policy-control.component.html
@@ -28,7 +28,7 @@
         <mat-cell *matCellDef="let policyType">
             <mat-icon matTooltip="Properties">{{isInstancesShown(policyType)  ? 'expand_less' : 'expand_more'}}
             </mat-icon>
-            {{this.getName(policyType)}}
+            {{this.getDisplayName(policyType)}}
         </mat-cell>
     </ng-container>
 
@@ -41,7 +41,8 @@
     <ng-container matColumnDef="action">
         <mat-header-cell class="action-cell" *matHeaderCellDef>Action </mat-header-cell>
         <mat-cell class="action-cell" *matCellDef="let policyType" (click)="$event.stopPropagation()">
-            <button mat-icon-button (click)="createPolicyInstance(policyType)">
+            <button [disabled]="this.isSchemaEmpty(policyType)" mat-icon-button
+                (click)="createPolicyInstance(policyType)">
                 <mat-icon matTooltip="Create instance">add_box</mat-icon>
             </button>
         </mat-cell>
diff --git a/webapp-frontend/src/app/policy-control/policy-control.component.ts b/webapp-frontend/src/app/policy-control/policy-control.component.ts
index cd8d948..4b9d85a 100644
--- a/webapp-frontend/src/app/policy-control/policy-control.component.ts
+++ b/webapp-frontend/src/app/policy-control/policy-control.component.ts
@@ -88,6 +88,10 @@
         info.isExpanded.next(!info.isExpanded.getValue());
     }
 
+    private isSchemaEmpty(policyType: PolicyType): boolean {
+        return Object.keys(policyType.schemaObject).length === 0;
+    }
+
     getPolicyTypeInfo(policyType: PolicyType): PolicyTypeInfo {
         let info: PolicyTypeInfo = this.policyTypeInfo.get(policyType.name);
         if (!info) {
@@ -97,9 +101,11 @@
         return info;
     }
 
-    getName(policyType: PolicyType): string {
-        if (policyType.schemaObject.title) { return policyType.schemaObject.title; }
-        return policyType.name;
+    getDisplayName(policyType: PolicyType): string {
+        if (policyType.schemaObject.title) {
+            return policyType.schemaObject.title;
+        }
+        return '< No type >';
     }
 
     isInstancesShown(policyType: PolicyType): boolean {
diff --git a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html
index d447c70..f052cca 100644
--- a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html
+++ b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html
@@ -78,7 +78,7 @@
                     [class.text-danger]="!formIsValid">
                     {{formIsValid ? 'Json' : 'Not valid'}}
                 </strong>
-                <span *ngIf="!formIsValid && !prettyValidationErrors">Invalid form</span>
+                <strong class="text-danger" *ngIf="!formIsValid && !prettyValidationErrors">Not submittable</strong>
                 <span *ngIf="prettyValidationErrors">— errors:</span>
                 <div *ngIf="prettyValidationErrors" class="text-danger" [innerHTML]="prettyValidationErrors"></div>
             </div>
diff --git a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts
index aea3453..60ffbd3 100644
--- a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts
+++ b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts
@@ -123,11 +123,20 @@
         if (!this.policyInstanceId) {
             this.fetchRics();
         }
+        if (this.isSchemaEmpty()) {
+            // Empty schema, hide form, show json instead
+            this.isVisible.form = false;
+            this.isVisible.json = true;
+        }
     }
 
     ngAfterViewInit() {
     }
 
+    private isSchemaEmpty(): boolean {
+        return Object.keys(this.jsonSchemaObject).length === 0;
+    }
+
     onSubmit() {
         if (this.policyInstanceId == null) {
             this.policyInstanceId = uuid.v4();
@@ -154,15 +163,18 @@
         this.liveFormData = formData;
     }
 
-    get prettyLiveFormData() {
+    get prettyLiveFormData(): string {
+        if (this.isSchemaEmpty()) {
+            return this.jsonAsString;
+        }
         return JSON.stringify(this.liveFormData, null, 2);
     }
 
-    get schemaAsString() {
+    get schemaAsString(): string {
         return JSON.stringify(this.jsonSchemaObject, null, 2);
     }
 
-    get jsonAsString() {
+    get jsonAsString(): string {
         return JSON.stringify(this.jsonObject, null, 2);
     }
 
diff --git a/webapp-frontend/src/app/services/policy/policy.service.ts b/webapp-frontend/src/app/services/policy/policy.service.ts
index b92e8f1..93f08e7 100644
--- a/webapp-frontend/src/app/services/policy/policy.service.ts
+++ b/webapp-frontend/src/app/services/policy/policy.service.ts
@@ -67,7 +67,7 @@
     }
 
     getPolicyInstances(policyTypeId: string): Observable<PolicyInstance[]> {
-        const url = this.buildPath(this.policyTypePath, policyTypeId, this.policyPath);
+        const url = this.buildPath(this.policyPath) + '?type=' + policyTypeId;
         return this.httpClient.get<PolicyInstance[]>(url);
     }
 
@@ -76,7 +76,7 @@
      * @returns Observable that should yield a policy instance
      */
     getPolicy(policyTypeId: string, policyInstanceId: string): Observable<any> {
-        const url = this.buildPath(this.policyTypePath, policyTypeId, this.policyPath, policyInstanceId);
+        const url = this.buildPath(this.policyPath, policyInstanceId) + '?type=' + policyTypeId;
         return this.httpClient.get<any>(url);
     }
 
@@ -88,7 +88,7 @@
      * @returns Observable that should yield a response code, no data
      */
     putPolicy(policyTypeId: string, policyInstanceId: string, policyJson: string, ric: string): Observable<any> {
-        const url = this.buildPath(this.policyTypePath, policyTypeId, this.policyPath, policyInstanceId) + '?ric=' + ric;
+        const url = this.buildPath(this.policyPath, policyInstanceId) + '?ric=' + ric + '&type=' + policyTypeId;
         return this.httpClient.put<PolicyInstanceAck>(url, policyJson, { observe: 'response' });
     }
 
@@ -99,7 +99,7 @@
      * @returns Observable that should yield a response code, no data
      */
     deletePolicy(policyTypeId: string, policyInstanceId: string): Observable<any> {
-        const url = this.buildPath(this.policyTypePath, policyTypeId, this.policyPath, policyInstanceId);
+        const url = this.buildPath(this.policyPath, policyInstanceId) + '?type=' + policyTypeId;
         return this.httpClient.delete(url, { observe: 'response' });
     }