http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CatalogController.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CatalogController.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CatalogController.java
new file mode 100644
index 0000000..6f66191
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CatalogController.java
@@ -0,0 +1,399 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.catalog.controller;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.catalog.api.dao.CatalogDao;
+import org.apache.logging.log4j.catalog.api.Attribute;
+import org.apache.logging.log4j.catalog.api.Category;
+import org.apache.logging.log4j.catalog.api.Event;
+import org.apache.logging.log4j.catalog.api.Product;
+import org.apache.logging.log4j.catalog.jpa.converter.AttributeModelConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.CategoryModelConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.EventModelConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.ProductModelConverter;
+import org.apache.logging.log4j.catalog.jpa.model.AttributeModel;
+import org.apache.logging.log4j.catalog.jpa.model.CategoryModel;
+import org.apache.logging.log4j.catalog.jpa.model.EventModel;
+import org.apache.logging.log4j.catalog.jpa.model.ProductModel;
+import org.apache.logging.log4j.catalog.jpa.service.AttributeService;
+import org.apache.logging.log4j.catalog.jpa.service.CategoryService;
+import org.apache.logging.log4j.catalog.jpa.service.EventService;
+import org.apache.logging.log4j.catalog.jpa.service.ProductService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import org.apache.logging.log4j.catalog.api.CatalogData;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * The Class CatalogController.
+ */
+@RestController
+public class CatalogController {
+
+       /** The logger. */
+       private static Logger logger = 
LogManager.getLogger(CatalogController.class);
+
+       @Autowired
+       private EventService eventService;
+
+       @Autowired
+       private AttributeService attributeService;
+
+       @Autowired
+       private ProductService productService;
+
+       @Autowired
+       private CategoryService categoryService;
+
+       @Autowired
+       private AttributeModelConverter attributeModelConverter;
+
+       @Autowired
+       private EventModelConverter eventModelConverter;
+
+       @Autowired
+       private ProductModelConverter productModelConverter;
+
+       @Autowired
+       private CategoryModelConverter categoryModelConverter;
+
+       @Autowired
+       private CatalogDao catalogDao;
+
+
+       @PostMapping(value = "/catalog/products/list")
+       public ResponseEntity<List<Product>> productList() {
+               return null;
+       }
+
+       @RequestMapping(value = "/catalog/events", method = RequestMethod.GET)
+       public ResponseEntity<Object> handleGetEventsList(
+                       @RequestParam(required = false) String eventList,
+                       @RequestParam(required = false) boolean 
attributeDetails,
+                       HttpServletRequest servletRequest) throws 
ParseException {
+
+               CatalogData catalogData = null;
+/*             try {
+                       if (!GenericValidator.isBlankOrNull(eventList)) {
+                               List<String> events = new 
ArrayList<>(StringUtils.commaDelimitedListToSet(eventList));
+                               catalogData = new CatalogData();
+                               catalogData.setEvents(new Events());
+                               for (String eventID : events) {
+                                       
globalLoggingCatalog.getEventById(eventID, catalogData.getEvents().getEvent());
+                               }
+                       } else {
+                               catalogData = globalLoggingCatalog.getEvents();
+                       }
+
+                       if (attributeDetails && catalogData != null
+                                       && catalogData.getEvents() != null) {
+                               List<Event> events = 
catalogData.getEvents().getEvent();
+                               for (Event event : events) {
+                                       if (event != null && 
event.getEventAttributes() != null) {
+                                               event.setAttributes(new 
Attributes());
+                                               List<String> attributes = 
event.getEventAttributes()
+                                                               .getAttribute();
+                                               for (String eventAttribute : 
attributes) {
+                                                       
globalLoggingCatalog.getAttributeByName(
+                                                                       
eventAttribute, event.getAttributes()
+                                                                               
        .getAttribute());
+                                               }
+                                       }
+                               }
+                       }
+               } catch (GLCatalogException e) {
+                       logger.error("Error While Retrieving Data", e);
+
+                       Status status = new Status();
+                       ErrorInfo errorInfo = new ErrorInfo();
+                       errorInfo.setErrorCode("00000");
+                       errorInfo.setErrorMessage(e.getMessage());
+                       status.getErrorInfo().add(errorInfo);
+                       status.setStatusMessage(e.getMessage());
+                       return new ResponseEntity<Object>(status,
+                                       HttpStatus.INTERNAL_SERVER_ERROR);
+               } */
+
+               return new ResponseEntity<Object>(catalogData, HttpStatus.OK);
+
+       }
+
+       @RequestMapping(value = "/catalog/events/{eventID}", method = 
RequestMethod.GET)
+       public ResponseEntity<Object> handleGetEvent(
+                       @PathVariable("eventID") String eventID,
+                       @RequestParam(required = false) boolean 
attributeDetails,
+                       HttpServletRequest servletRequest) {
+
+               CatalogData catalogData = null;
+       /*      try {
+                       catalogData = 
globalLoggingCatalog.getEventById(eventID);
+
+                       if (attributeDetails
+                                       && catalogData != null
+                                       && catalogData.getEvents() != null
+                                       && 
catalogData.getEvents().getEvent().get(0) != null
+                                       && 
catalogData.getEvents().getEvent().get(0)
+                                                       .getEventAttributes() 
!= null) {
+                               List<String> eventAttributes = 
catalogData.getEvents()
+                                               
.getEvent().get(0).getEventAttributes().getAttribute();
+                               logger.debug("event attributes count: "
+                                               + eventAttributes.size());
+                               catalogData.getEvents().getEvent().get(0)
+                                               .setAttributes(new 
Attributes());
+                               for (String eventAttribute : eventAttributes) {
+                                       
globalLoggingCatalog.getAttributeByName(eventAttribute,
+                                                       
catalogData.getEvents().getEvent().get(0)
+                                                                       
.getAttributes().getAttribute());
+                               }
+                       }
+
+               } catch (Exception e) {
+                       logger.error("Error While Retrieving Data", e);
+
+                       Status status = new Status();
+                       ErrorInfo errorInfo = new ErrorInfo();
+                       errorInfo.setErrorCode("00000");
+                       errorInfo.setErrorMessage(e.getMessage());
+                       status.getErrorInfo().add(errorInfo);
+                       status.setStatusMessage(e.getMessage());
+                       return new ResponseEntity<Object>(status,
+                                       HttpStatus.INTERNAL_SERVER_ERROR);
+               } */
+
+               return new ResponseEntity<Object>(catalogData, HttpStatus.OK);
+
+       }
+
+       @RequestMapping(value = "/catalog/attributes", method = 
RequestMethod.GET)
+       public ResponseEntity<Object> handleGetAttributesList(
+                       @RequestParam(required = false) String attributeList,
+                       HttpServletRequest servletRequest) {
+
+               CatalogData catalogData = null;
+       /*      try {
+
+                       if (!GenericValidator.isBlankOrNull(attributeList)) {
+                               List<String> attributes = new ArrayList<String>(
+                                               
StringUtils.commaDelimitedListToSet(attributeList));
+                               catalogData = new CatalogData();
+                               catalogData.setAttributes(new Attributes());
+                               for (String attribute : attributes) {
+                                       
globalLoggingCatalog.getAttributeByName(attribute,
+                                                       
catalogData.getAttributes().getAttribute());
+                               }
+                       } else {
+
+                               catalogData = 
globalLoggingCatalog.getAttributes();
+                       }
+               } catch (GLCatalogException e) {
+                       logger.error("Error While Retrieving Data", e);
+
+                       Status status = new Status();
+                       ErrorInfo errorInfo = new ErrorInfo();
+                       errorInfo.setErrorCode("00000");
+                       errorInfo.setErrorMessage(e.getMessage());
+                       status.getErrorInfo().add(errorInfo);
+                       status.setStatusMessage(e.getMessage());
+                       return new ResponseEntity<Object>(status,
+                                       HttpStatus.INTERNAL_SERVER_ERROR);
+               } */
+
+               return new ResponseEntity<Object>(catalogData, HttpStatus.OK);
+
+       }
+
+       @RequestMapping(value = "/catalog/attributes/{attribute}", method = 
RequestMethod.GET)
+       public ResponseEntity<Object> handleGetAttribute(
+                       @PathVariable("attribute") String attribute,
+                       HttpServletRequest servletRequest) throws 
ParseException {
+
+               CatalogData catalogData = null;
+/*             try {
+                       catalogData = 
globalLoggingCatalog.getAttributeByName(attribute);
+               } catch (GLCatalogException e) {
+                       logger.error("Error While Retrieving Data", e);
+
+                       Status status = new Status();
+                       ErrorInfo errorInfo = new ErrorInfo();
+                       errorInfo.setErrorCode("00000");
+                       errorInfo.setErrorMessage(e.getMessage());
+                       status.getErrorInfo().add(errorInfo);
+                       status.setStatusMessage(e.getMessage());
+                       return new ResponseEntity<Object>(status,
+                                       HttpStatus.INTERNAL_SERVER_ERROR);
+               } */
+
+               return new ResponseEntity<Object>(catalogData, HttpStatus.OK);
+
+       }
+
+       @RequestMapping(value = "/catalog/categories", method = 
RequestMethod.GET)
+       public ResponseEntity<Object> handleGetCategoriesList(
+                       @RequestParam(required = false) String categoryList,
+                       HttpServletRequest servletRequest) {
+
+               CatalogData catalogData = null;
+/*             try {
+                       if (!GenericValidator.isBlankOrNull(categoryList)) {
+                               List<String> categories = new ArrayList<String>(
+                                               
StringUtils.commaDelimitedListToSet(categoryList));
+                               catalogData = new CatalogData();
+                               catalogData.setCategories(new Categories());
+                               for (String category : categories) {
+                                       
globalLoggingCatalog.getCategoryByName(category,
+                                                       
catalogData.getCategories().getCategory());
+                               }
+                       } else {
+                               catalogData = 
globalLoggingCatalog.getCategories();
+                       }
+               } catch (GLCatalogException e) {
+                       logger.error("Error While Retrieving Data", e);
+
+                       Status status = new Status();
+                       ErrorInfo errorInfo = new ErrorInfo();
+                       errorInfo.setErrorCode("00000");
+                       errorInfo.setErrorMessage(e.getMessage());
+                       status.getErrorInfo().add(errorInfo);
+                       status.setStatusMessage(e.getMessage());
+                       return new ResponseEntity<Object>(status,
+                                       HttpStatus.INTERNAL_SERVER_ERROR);
+               } */
+
+               return new ResponseEntity<Object>(catalogData, HttpStatus.OK);
+
+       }
+
+       @RequestMapping(value = "/catalog/categories/{category}", method = 
RequestMethod.GET)
+       public ResponseEntity<Object> handleGetCategory(
+                       @PathVariable("category") String category,
+                       HttpServletRequest servletRequest) throws 
ParseException {
+
+               CatalogData catalogData = null;
+       /*      try {
+                       catalogData = 
globalLoggingCatalog.getCategoryByName(category);
+               } catch (GLCatalogException e) {
+                       logger.error("Error While Retrieving Data", e);
+
+                       Status status = new Status();
+                       ErrorInfo errorInfo = new ErrorInfo();
+                       errorInfo.setErrorCode("00000");
+                       errorInfo.setErrorMessage(e.getMessage());
+                       status.getErrorInfo().add(errorInfo);
+                       status.setStatusMessage(e.getMessage());
+                       return new ResponseEntity<Object>(status,
+                                       HttpStatus.INTERNAL_SERVER_ERROR);
+               } */
+
+               return new ResponseEntity<Object>(catalogData, HttpStatus.OK);
+
+       }
+
+       @PostMapping(value = "catalog")
+       public ResponseEntity<?> saveCatalog() {
+               CatalogData catalogData = new CatalogData();
+               List<Attribute> attributes = new ArrayList<>();
+               for (AttributeModel attributeModel : 
attributeService.getAttributes()) {
+                       
attributes.add(attributeModelConverter.convert(attributeModel));
+               }
+               catalogData.setAttributes(attributes);
+               List<Event> events = new ArrayList<>();
+               for (EventModel eventModel : eventService.getEvents()) {
+                       events.add(eventModelConverter.convert(eventModel));
+               }
+               catalogData.setEvents(events);
+               List<Category> categories = new ArrayList<>();
+               for (CategoryModel categoryModel : 
categoryService.getCategories()) {
+                       
categories.add(categoryModelConverter.convert(categoryModel));
+               }
+               catalogData.setCategories(categories);
+               List<Product> products = new ArrayList<>();
+               for (ProductModel productModel : productService.getProducts()) {
+                       
products.add(productModelConverter.convert(productModel));
+               }
+               catalogData.setProducts(products);
+               catalogDao.write(catalogData);
+               return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+       }
+/*
+       @RequestMapping(value = "/catalog", method = RequestMethod.GET)
+       public ResponseEntity<Object> handleGetCatalog(
+                       @RequestParam(required = false) boolean 
attributeDetails,
+                       HttpServletRequest servletRequest) {
+               CatalogData catalogData = null;
+               try {
+                       //catalogData = globalLoggingCatalog.getCatalog();
+                       if (attributeDetails) {
+                               getAttributeDetailsForEvents(catalogData);
+                       }
+                       return new ResponseEntity<Object>(catalogData, 
HttpStatus.OK);
+
+               } catch (Exception e) {
+                       logger.error("Error While Retrieving Data", e);
+
+                       Status status = new Status();
+                       ErrorInfo errorInfo = new ErrorInfo();
+                       errorInfo.setErrorCode("00000");
+                       errorInfo.setErrorMessage(e.getMessage());
+                       status.getErrorInfo().add(errorInfo);
+                       status.setStatusMessage(e.getMessage());
+                       return new ResponseEntity<Object>(status,
+                                       HttpStatus.INTERNAL_SERVER_ERROR);
+               }
+
+
+       } */
+
+       private void getAttributeDetailsForEvents(CatalogData catalogData) {
+       /*      for (Event _event : catalogData.getEvents().getEvent()) {
+                       if (_event != null && _event.getEventAttributes() != 
null) {
+
+                               List<String> eventAttributes = 
_event.getEventAttributes()
+                                               .getAttribute();
+                               _event.setAttributes(new Attributes());
+                               for (String eventAttribute : eventAttributes) {
+                                       
globalLoggingCatalog.getAttributeByName(eventAttribute,
+                                                       
_event.getAttributes().getAttribute());
+                               }
+                       }
+               }*/
+       }
+
+       /**
+        * Sets the global log service.
+        *
+        * @param globalLoggingService
+        *            the global log service
+        */
+/*     public void setGlobalLogCatalog(GlobalLoggingCatalog 
globalLoggingCatalog) {
+               this.globalLoggingCatalog = globalLoggingCatalog;
+       } */
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CategoryController.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CategoryController.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CategoryController.java
new file mode 100644
index 0000000..1a0c4ea
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/CategoryController.java
@@ -0,0 +1,130 @@
+package org.apache.logging.log4j.catalog.controller;
+
+import javax.annotation.PostConstruct;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.catalog.api.Category;
+import org.apache.logging.log4j.catalog.jpa.model.CategoryModel;
+import org.apache.logging.log4j.catalog.jpa.service.CategoryService;
+import org.apache.logging.log4j.catalog.jpa.converter.CategoryConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.CategoryModelConverter;
+import org.modelmapper.ModelMapper;
+import org.modelmapper.TypeToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Catalog Category controller
+ */
+
+@RequestMapping(value = "/api/categories")
+@RestController
+public class CategoryController {
+    private static final Logger LOGGER = LogManager.getLogger();
+
+    private ModelMapper modelMapper = new ModelMapper();
+
+    @Autowired
+    private CategoryService categoryService;
+
+
+    @Autowired
+    private CategoryModelConverter categoryModelConverter;
+
+    @Autowired
+    private CategoryConverter categoryConverter;
+
+    @PostConstruct
+    public void init() {
+        modelMapper.addConverter(categoryModelConverter);
+    }
+
+    @PostMapping(value = "/list")
+    public ResponseEntity<Map<String, Object>> 
categoryList(@RequestParam(value="jtStartIndex", required=false) Integer 
startIndex,
+                                                            
@RequestParam(value="jtPageSize", required=false) Integer pageSize,
+                                                            
@RequestParam(value="jtSorting", required=false) String sorting) {
+        Type listType = new TypeToken<List<Category>>() {}.getType();
+        Map<String, Object> response = new HashMap<>();
+        try {
+            List<Category> categories = null;
+            if (startIndex == null || pageSize == null) {
+                categories = modelMapper.map(categoryService.getCategories(), 
listType);
+            } else {
+                int startPage = 0;
+                if (startIndex > 0) {
+                    startPage = startIndex / pageSize;
+                }
+                String sortColumn = "name";
+                String sortDirection = "ASC";
+                if (sorting != null) {
+                    String[] sortInfo = sorting.split(" ");
+                    sortColumn = sortInfo[0];
+                    if (sortInfo.length > 0) {
+                        sortDirection = sortInfo[1];
+                    }
+                }
+                categories = 
modelMapper.map(categoryService.getCategories(startPage, pageSize, sortColumn, 
sortDirection), listType);
+            }
+            if (categories == null) {
+                categories = new ArrayList<>();
+            }
+            response.put("Result", "OK");
+            response.put("Records", categories);
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/create")
+    public ResponseEntity<Map<String, Object>> createCategory(@RequestBody 
Category category) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            CategoryModel model = categoryConverter.convert(category);
+            model = categoryService.saveCategory(model);
+            response.put("Result", "OK");
+            response.put("Records", categoryModelConverter.convert(model));
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/update")
+    public ResponseEntity<Map<String, Object>> updateCategory(@RequestBody 
Category category) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            CategoryModel model = categoryConverter.convert(category);
+            model = categoryService.saveCategory(model);
+            response.put("Result", "OK");
+            response.put("Records", categoryModelConverter.convert(model));
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/delete")
+    public ResponseEntity<Map<String, Object>> deleteCategory(@RequestBody 
Category category) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            categoryService.deleteCategory(category.getId());
+            response.put("Result", "OK");
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ConstraintController.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ConstraintController.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ConstraintController.java
new file mode 100644
index 0000000..bb5288f
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ConstraintController.java
@@ -0,0 +1,86 @@
+package org.apache.logging.log4j.catalog.controller;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.catalog.api.Attribute;
+import org.apache.logging.log4j.catalog.api.Constraint;
+import org.apache.logging.log4j.catalog.jpa.model.ConstraintModel;
+import org.apache.logging.log4j.catalog.jpa.service.ConstraintService;
+import org.modelmapper.ModelMapper;
+import org.modelmapper.TypeToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Constraint controller
+ */
+
+@RequestMapping(value = "/api/constraints")
+@RestController
+public class ConstraintController {
+    private static final Logger LOGGER = LogManager.getLogger();
+
+    private ModelMapper modelMapper = new ModelMapper();
+
+    @Autowired
+    private ConstraintService constraintService;
+
+    @PostMapping(value = "/list")
+    public ResponseEntity<Map<String, Object>> 
attributeList(@RequestParam("attributeId") Long attributeId) {
+        Type listType = new TypeToken<List<Attribute>>() {}.getType();
+        Map<String, Object> response = new HashMap<>();
+        try {
+            List<Attribute> attributes = 
modelMapper.map(constraintService.getConstraints(), listType);
+            if (attributes == null) {
+                attributes = new ArrayList<>();
+            }
+            response.put("Result", "OK");
+            response.put("Records", attributes);
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @GetMapping(value = "/types")
+    public ResponseEntity<Set<String>> getConstraintTypes() {
+        return new ResponseEntity<>(constraintService.getConstraintTypes(), 
HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/constraint")
+    public ResponseEntity<Long> addConstraint(@RequestBody Constraint 
constraint) {
+        ConstraintModel model = modelMapper.map(constraint, 
ConstraintModel.class);
+        model = constraintService.saveConstraint(model);
+        return new ResponseEntity<>(model.getId(), HttpStatus.CREATED);
+    }
+
+    @PutMapping(value = "/constraint/{id}")
+    public ResponseEntity<Long> updateConstraint(@RequestParam Long id, 
@RequestBody Constraint constraint) {
+        ConstraintModel model = modelMapper.map(constraint, 
ConstraintModel.class);
+        model.setId(id);
+        model = constraintService.saveConstraint(model);
+        return new ResponseEntity<>(model.getId(), HttpStatus.OK);
+    }
+
+    @DeleteMapping(value = "/constraint/{id}")
+    public ResponseEntity<?> deleteConstraint(@RequestParam Long id) {
+        constraintService.deleteConstraint(id);
+        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/EventController.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/EventController.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/EventController.java
new file mode 100644
index 0000000..a7a5746
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/EventController.java
@@ -0,0 +1,158 @@
+package org.apache.logging.log4j.catalog.controller;
+
+import javax.annotation.PostConstruct;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.catalog.api.Event;
+import org.apache.logging.log4j.catalog.jpa.model.EventModel;
+import org.apache.logging.log4j.catalog.jpa.service.EventService;
+import org.apache.logging.log4j.catalog.jpa.converter.EventConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.EventModelConverter;
+import org.modelmapper.ModelMapper;
+import org.modelmapper.TypeToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Catalog Product controller
+ */
+
+@RequestMapping(value = "/api/events")
+@RestController
+public class EventController {
+    private static final Logger LOGGER = LogManager.getLogger();
+
+    private ModelMapper modelMapper = new ModelMapper();
+
+    @Autowired
+    private EventService eventService;
+
+    @Autowired
+    private EventModelConverter eventModelConverter;
+
+    @Autowired
+    private EventConverter eventConverter;
+
+    @PostConstruct
+    public void init() {
+        modelMapper.addConverter(eventModelConverter);
+    }
+
+    @PostMapping(value = "/list")
+    public ResponseEntity<Map<String, Object>> 
eventList(@RequestParam(value="jtStartIndex", required=false) Integer 
startIndex,
+                                                         
@RequestParam(value="jtPageSize", required=false) Integer pageSize,
+                                                         
@RequestParam(value="jtSorting", required=false) String sorting) {
+        Type listType = new TypeToken<List<Event>>() {}.getType();
+        Map<String, Object> response = new HashMap<>();
+        try {
+            List<Event> events = null;
+            if (startIndex == null || pageSize == null) {
+                events = modelMapper.map(eventService.getEvents(), listType);
+            } else {
+                int startPage = 0;
+                if (startIndex > 0) {
+                    startPage = startIndex / pageSize;
+                }
+                String sortColumn = "name";
+                String sortDirection = "ASC";
+                if (sorting != null) {
+                    String[] sortInfo = sorting.split(" ");
+                    sortColumn = sortInfo[0];
+                    if (sortInfo.length > 0) {
+                        sortDirection = sortInfo[1];
+                    }
+                }
+                events = modelMapper.map(eventService.getEvents(startPage, 
pageSize, sortColumn, sortDirection), listType);
+            }
+            if (events == null) {
+                events = new ArrayList<>();
+            }
+            response.put("Result", "OK");
+            response.put("Records", events);
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+            response.put("Message", ex.getMessage());
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/create")
+    public ResponseEntity<Map<String, Object>> createEvent(@RequestBody Event 
event) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            EventModel model = eventConverter.convert(event);
+            event = eventModelConverter.convert(eventService.saveEvent(model));
+            response.put("Result", "OK");
+            response.put("Records", event);
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+            response.put("Message", ex.getMessage());
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/update")
+    public ResponseEntity<Map<String, Object>> updateEvent(@RequestBody Event 
event) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            EventModel model = eventConverter.convert(event);
+            event = eventModelConverter.convert(eventService.saveEvent(model));
+            response.put("Result", "OK");
+            response.put("Records", event);
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+            response.put("Message", ex.getMessage());
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/delete")
+    public ResponseEntity<Map<String, Object>> deleteEvent(@RequestBody Long 
eventId) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            eventService.deleteEvent(eventId);
+            response.put("Result", "OK");
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+            response.put("Message", ex.getMessage());
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/attributes/list")
+    public ResponseEntity<Map<String, Object>> 
attributeList(@RequestParam("eventId") Long eventId) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            Optional<EventModel> optional = eventService.getEvent(eventId);
+            if (optional.isPresent()) {
+                Event event = eventModelConverter.convert(optional.get());
+                response.put("Result", "OK");
+                if (event != null && event.getAttributes() != null) {
+                    response.put("Records", event.getAttributes());
+                } else {
+                    response.put("Records", new ArrayList<>());
+                }
+            } else {
+                response.put("Result", "OK");
+                response.put("Records", new ArrayList<>());
+
+            }
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ProductController.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ProductController.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ProductController.java
new file mode 100644
index 0000000..9d663a8
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/ProductController.java
@@ -0,0 +1,130 @@
+package org.apache.logging.log4j.catalog.controller;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.catalog.api.Product;
+import org.apache.logging.log4j.catalog.jpa.model.ProductModel;
+import org.apache.logging.log4j.catalog.jpa.service.ProductService;
+import org.apache.logging.log4j.catalog.jpa.converter.ProductConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.ProductModelConverter;
+import org.modelmapper.ModelMapper;
+import org.modelmapper.TypeToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Catalog Product controller
+ */
+
+@RequestMapping(value = "/api/products")
+@RestController
+public class ProductController {
+    private static final Logger LOGGER = LogManager.getLogger();
+
+    private ModelMapper modelMapper = new ModelMapper();
+
+    @Autowired
+    private ProductService productService;
+
+    @Autowired
+    private ProductModelConverter productModelConverter;
+
+    @Autowired
+    private ProductConverter productConverter;
+
+    @PostConstruct
+    public void init() {
+        modelMapper.addConverter(productModelConverter);
+    }
+
+    @PostMapping(value = "/list")
+    public ResponseEntity<Map<String, Object>> 
productList(@RequestParam(value="jtStartIndex", required=false) Integer 
startIndex,
+                                                           
@RequestParam(value="jtPageSize", required=false) Integer pageSize,
+                                                           
@RequestParam(value="jtSorting", required=false) String sorting) {
+        Type listType = new TypeToken<List<Product>>() {}.getType();
+        Map<String, Object> response = new HashMap<>();
+        try {
+            List<Product> products = null;
+            if (startIndex == null || pageSize == null) {
+                products = modelMapper.map(productService.getProducts(), 
listType);
+            } else {
+                int startPage = 0;
+                if (startIndex > 0) {
+                    startPage = startIndex / pageSize;
+                }
+                String sortColumn = "name";
+                String sortDirection = "ASC";
+                if (sorting != null) {
+                    String[] sortInfo = sorting.split(" ");
+                    sortColumn = sortInfo[0];
+                    if (sortInfo.length > 0) {
+                        sortDirection = sortInfo[1];
+                    }
+                }
+                products = 
modelMapper.map(productService.getProducts(startPage, pageSize, sortColumn, 
sortDirection), listType);
+            }
+            if (products == null) {
+                products = new ArrayList<>();
+            }
+            response.put("Result", "OK");
+            response.put("Records", products);
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/create")
+    public ResponseEntity<Map<String, Object>> createProduct(@RequestBody 
Product product) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            ProductModel model = productConverter.convert(product);
+            model = productService.saveProduct(model);
+            response.put("Result", "OK");
+            response.put("Records", productModelConverter.convert(model));
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/update")
+    public ResponseEntity<Map<String, Object>> updateProduct(@RequestBody 
Product product) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            ProductModel model = productConverter.convert(product);
+            model = productService.saveProduct(model);
+            response.put("Result", "OK");
+            response.put("Records", productModelConverter.convert(model));
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    @PostMapping(value = "/delete")
+    public ResponseEntity<Map<String, Object>> deleteProduct(@RequestBody 
Product product) {
+        Map<String, Object> response = new HashMap<>();
+        try {
+            productService.deleteProduct(product.getId());
+            response.put("Result", "OK");
+        } catch (Exception ex) {
+            response.put("Result", "FAILURE");
+        }
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/RestResponseEntityExceptionHandler.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/RestResponseEntityExceptionHandler.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/RestResponseEntityExceptionHandler.java
new file mode 100644
index 0000000..b420b16
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/controller/RestResponseEntityExceptionHandler.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.catalog.controller;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.data.rest.webmvc.support.ExceptionMessage;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import 
org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+@ControllerAdvice
+public class RestResponseEntityExceptionHandler extends 
ResponseEntityExceptionHandler {
+    private static final Logger LOGGER = LogManager.getLogger();
+
+    @ExceptionHandler({ Exception.class })
+    @ResponseBody
+    public ResponseEntity<?> handleAnyException(Exception e) {
+        return errorResponse(e, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+
+    protected ResponseEntity<ExceptionMessage> errorResponse(Throwable 
throwable,
+                                                             HttpStatus 
status) {
+        if (null != throwable) {
+            LOGGER.error("error caught: " + throwable.getMessage(), throwable);
+            return response(new ExceptionMessage(throwable), status);
+        } else {
+            LOGGER.error("unknown error caught in RESTController, {}", status);
+            return response(null, status);
+        }
+    }
+
+    protected <T> ResponseEntity<T> response(T body, HttpStatus status) {
+        LOGGER.debug("Responding with a status of {}", status);
+        return new ResponseEntity<>(body, new HttpHeaders(), status);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/interceptor/RequestContextHeaderInterceptor.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/interceptor/RequestContextHeaderInterceptor.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/interceptor/RequestContextHeaderInterceptor.java
new file mode 100644
index 0000000..520fb1a
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/interceptor/RequestContextHeaderInterceptor.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.catalog.interceptor;
+
+import java.io.IOException;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+
+/**
+ * Creates a List of Headers containing the keys and values in the 
RequestContext that have a mapping indicating
+ * they should be propogated to the service being called.
+ *
+ * This class is designed to be used by Spring as part of the REST Template 
configuration.
+ *
+ */
+public class RequestContextHeaderInterceptor implements 
ClientHttpRequestInterceptor {
+
+    @Override
+    public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body,
+                                        ClientHttpRequestExecution 
clientHttpRequestExecution) throws IOException {
+        return clientHttpRequestExecution.execute(httpRequest, body);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/security/LocalAuthorizationInterceptor.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/security/LocalAuthorizationInterceptor.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/security/LocalAuthorizationInterceptor.java
new file mode 100644
index 0000000..d3521d5
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/security/LocalAuthorizationInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.catalog.security;
+
+
+import org.apache.http.HttpStatus;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+public class LocalAuthorizationInterceptor extends HandlerInterceptorAdapter {
+    private static final Logger LOGGER = LogManager.getLogger();
+    private final String token;
+
+    public LocalAuthorizationInterceptor(String token) {
+        this.token = token;
+    }
+
+    @Override
+    public boolean preHandle(javax.servlet.http.HttpServletRequest request, 
javax.servlet.http.HttpServletResponse response, Object handler) throws 
Exception {
+        LOGGER.traceEntry();
+        try {
+            if (request.getServletPath().startsWith("/swagger")) {
+                return true;
+            }
+
+            String authHeader = request.getHeader("Authorization");
+            if (authHeader == null || !authHeader.equals(token)) {
+                LOGGER.error("Authorization value of " + authHeader + " does 
not match expected value of " + token);
+                response.sendError(HttpStatus.SC_UNAUTHORIZED);
+                return false;
+            }
+
+            return true;
+        } finally {
+            LOGGER.traceExit();
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/service/CatalogInitializer.java
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/service/CatalogInitializer.java
 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/service/CatalogInitializer.java
new file mode 100644
index 0000000..6b9f4be
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/java/org/apache/logging/log4j/catalog/service/CatalogInitializer.java
@@ -0,0 +1,99 @@
+package org.apache.logging.log4j.catalog.service;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.catalog.api.dao.CatalogDao;
+import org.apache.logging.log4j.catalog.api.Attribute;
+import org.apache.logging.log4j.catalog.api.CatalogData;
+import org.apache.logging.log4j.catalog.api.Category;
+import org.apache.logging.log4j.catalog.api.Event;
+import org.apache.logging.log4j.catalog.api.Product;
+import org.apache.logging.log4j.catalog.jpa.converter.AttributeConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.CategoryConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.EventConverter;
+import org.apache.logging.log4j.catalog.jpa.converter.ProductConverter;
+import org.apache.logging.log4j.catalog.jpa.model.AttributeModel;
+import org.apache.logging.log4j.catalog.jpa.model.CategoryModel;
+import org.apache.logging.log4j.catalog.jpa.model.EventModel;
+import org.apache.logging.log4j.catalog.jpa.model.ProductModel;
+import org.apache.logging.log4j.catalog.jpa.service.AttributeService;
+import org.apache.logging.log4j.catalog.jpa.service.CategoryService;
+import org.apache.logging.log4j.catalog.jpa.service.EventService;
+import org.apache.logging.log4j.catalog.jpa.service.ProductService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ */
+@Component
+public class CatalogInitializer {
+    private static final Logger logger = 
LogManager.getLogger(CatalogInitializer.class);
+
+    @Autowired
+    AttributeService attributeService;
+
+    @Autowired
+    EventService eventService;
+
+    @Autowired
+    CategoryService categoryService;
+
+    @Autowired
+    ProductService productService;
+
+    @Autowired
+    CatalogDao catalogDao;
+
+    @Autowired
+    AttributeConverter attributeConverter;
+
+    @Autowired
+    EventConverter eventConverter;
+
+    @Autowired
+    CategoryConverter categoryConverter;
+
+    @Autowired
+    ProductConverter productConverter;
+
+    @PostConstruct
+    private void initialize() {
+        logger.debug("Performing initialization");
+        CatalogData catalogData = catalogDao.read();
+
+        logger.debug("Loading attributes");
+        List<AttributeModel> attributeModels = new ArrayList<>();
+        for (Attribute attribute : catalogData.getAttributes()) {
+            AttributeModel model = attributeConverter.convert(attribute);
+            attributeService.saveAttribute(model);
+            attributeModels.add(model);
+        }
+        eventConverter.setAttributes(attributeModels);
+        Map<String, EventModel> eventMap = new HashMap<>();
+        logger.debug("Loading events");
+        for (Event event : catalogData.getEvents()) {
+            logger.debug("Processing Event: {}", event);
+            EventModel model = eventConverter.convert(event);
+            logger.debug("Created EventModel: {} ", model);
+            eventMap.put(event.getName(), model);
+            eventService.saveEvent(model);
+        }
+        logger.debug("Loading categories");
+        for (Category category : catalogData.getCategories()) {
+            CategoryModel model = categoryConverter.convert(category);
+            categoryService.saveCategory(model);
+        }
+        logger.debug("loading products");
+        for (Product product : catalogData.getProducts()) {
+            ProductModel model = productConverter.convert(product);
+            productService.saveProduct(model);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/application.properties
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/application.properties
 
b/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/application.properties
new file mode 100644
index 0000000..9ea7caf
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/application.properties
@@ -0,0 +1,2 @@
+dataSource.jdbcUsername=AES:Or9VPVQryD97GfO9dVJggA==
+dataSource.jdbcPassword=AES:Or9VPVQryD97GfO9dVJggA==
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/lab.properties
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/lab.properties
 
b/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/lab.properties
new file mode 100644
index 0000000..396b461
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/resources/CatalogService/lab.properties
@@ -0,0 +1,2 @@
+http.client.socket.timeout=1100
+http.client.connect.timeout=1100

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/log4j-catalog/log4j-catalog-war/src/main/resources/log4j2.xml 
b/log4j-catalog/log4j-catalog-war/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..34e18ec
--- /dev/null
+++ b/log4j-catalog/log4j-catalog-war/src/main/resources/log4j2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements. See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache license, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License. You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the license for the specific language governing permissions and
+  ~ limitations under the license.
+  -->
+<Configuration status="ERROR">
+    <properties>
+        <property 
name="LOG_DIR">${sys:catalina.home}/logs/AuditCatalog</property>
+    </properties>
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d{ABSOLUTE} %-5level # %class.%method 
%m%n" />
+        </Console>
+
+        <RollingFile name="log4j" fileName="${LOG_DIR}/log4j.txt" 
filePattern="${LOG_DIR}/archive/log4j.txt.%d{yyyyMMdd_HH}-%i">
+            <PatternLayout pattern="%d [%t] %-5p %C{1.}.%M:%L - %m%n"/>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="30 MB"/>
+            </Policies>
+            <DefaultRolloverStrategy min="1" max="20"/>
+        </RollingFile>
+    </Appenders>
+    <Loggers>
+        <Logger name="org.apache.logging.log4j.catalog" level="WARN" 
additivity="false">
+            <AppenderRef ref="log4j"/>
+        </Logger>
+        <Root level="INFO">
+            <AppenderRef ref="log4j" />
+        </Root>
+    </Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/attributes.html
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/attributes.html
 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/attributes.html
new file mode 100644
index 0000000..0d4c04f
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/attributes.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+    <title>Audit Catalog - Attributes</title>
+
+    <!-- Include one of jTable styles. -->
+    <link href="js/jtable.2.4.0/themes/metro/blue/jtable.min.css" 
rel="stylesheet" type="text/css" />
+    <!-- Include app styles. -->
+    <link href="css/app.css" rel="stylesheet" type="text/css" />
+
+    <!-- Include jTable script file. -->
+    <script src="js/jquery-3.2.1.min.js" type="text/javascript"></script>
+    <script src="js/jquery-ui-1.12.1/jquery-ui.min.js" 
type="text/javascript"></script>
+    <script src="js/jtable.2.4.0/jquery.jtable.js" 
type="text/javascript"></script>
+    <!-- Include app script files. -->
+    <script src="js/app.js" type="text/javascript"></script>
+    <script src="js/attributes.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+    <div th:insert="~{template :: hdr}"></div>
+
+    <div id="AttributesTableContainer"></div>
+
+    <div th:insert="~{template :: ftr}"></div>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/categories.html
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/categories.html
 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/categories.html
new file mode 100644
index 0000000..c565197
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/categories.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+    <title>Audit Catalog - categories</title>
+
+    <!-- Include one of jTable styles. -->
+    <link href="js/jtable.2.4.0/themes/metro/blue/jtable.min.css" 
rel="stylesheet" type="text/css" />
+    <!-- Include app styles. -->
+    <link href="css/app.css" rel="stylesheet" type="text/css" />
+
+    <!-- Include jTable script file. -->
+    <script src="js/jquery-3.2.1.min.js" type="text/javascript"></script>
+    <script src="js/jquery-ui-1.12.1/jquery-ui.min.js" 
type="text/javascript"></script>
+    <script src="js/jtable.2.4.0/jquery.jtable.js" 
type="text/javascript"></script>
+    <!-- Include app script files. -->
+    <script src="js/app.js" type="text/javascript"></script>
+    <script src="js/categories.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+    <div th:insert="~{template :: hdr}"></div>
+
+    <div id="CategoriesTableContainer"></div>
+
+    <div th:insert="~{template :: ftr}"></div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/events.html
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/events.html 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/events.html
new file mode 100644
index 0000000..c00dcfd
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/events.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+    <title>Audit Catalog - Events</title>
+
+    <!-- Include one of jTable styles. -->
+    <link href="js/jtable.2.4.0/themes/metro/blue/jtable.min.css" 
rel="stylesheet" type="text/css" />
+    <!-- Include app styles. -->
+    <link href="css/app.css" rel="stylesheet" type="text/css" />
+
+    <!-- Include jTable script file. -->
+    <script src="js/jquery-3.2.1.min.js" type="text/javascript"></script>
+    <script src="js/jquery-ui-1.12.1/jquery-ui.min.js" 
type="text/javascript"></script>
+    <script src="js/jtable.2.4.0/jquery.jtable.js" 
type="text/javascript"></script>
+    <!-- Include app script files. -->
+    <script src="js/app.js" type="text/javascript"></script>
+    <script src="js/events.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+    <div th:insert="~{template :: hdr}"></div>
+
+    <div id="EventsTableContainer"></div>
+
+    <div th:insert="~{template :: ftr}"></div>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/products.html
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/products.html
 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/products.html
new file mode 100644
index 0000000..ed555f1
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/products.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+    <title>Audit Catalog - Products</title>
+
+    <!-- Include one of jTable styles. -->
+    <link href="js/jtable.2.4.0/themes/metro/blue/jtable.min.css" 
rel="stylesheet" type="text/css" />
+    <!-- Include app styles. -->
+    <link href="css/app.css" rel="stylesheet" type="text/css" />
+
+    <!-- Include jTable script file. -->
+    <script src="js/jquery-3.2.1.min.js" type="text/javascript"></script>
+    <script src="js/jquery-ui-1.12.1/jquery-ui.min.js" 
type="text/javascript"></script>
+    <script src="js/jtable.2.4.0/jquery.jtable.js" 
type="text/javascript"></script>
+    <!-- Include app script files. -->
+    <script src="js/app.js" type="text/javascript"></script>
+    <script src="js/products.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+    <div th:insert="~{template :: hdr}"></div>
+
+    <div id="ProductsTableContainer"></div>
+
+    <div th:insert="~{template :: ftr}"></div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/template.html
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/template.html
 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/template.html
new file mode 100644
index 0000000..8178bad
--- /dev/null
+++ 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/WEB-INF/templates/template.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+
+<html xmlns:th="http://www.thymeleaf.org";>
+
+<body>
+
+    <div th:fragment="hdr">
+        <div id="nav">
+            <a href="products">Products</a>
+            <a href="categories">Categories</a>
+            <a href="events">Events</a>
+            <a href="attributes">Attributes</a>
+          </div>
+    </div>
+
+    <div th:fragment="ftr">
+        <div id="ftr">
+            &copy; 2017 log4jCatalog
+        </div>
+        <div id="log4jtooltip"></div>
+    </div>
+
+</body>
+
+</html>

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/css/app.css
----------------------------------------------------------------------
diff --git a/log4j-catalog/log4j-catalog-war/src/main/webapp/css/app.css 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/css/app.css
new file mode 100644
index 0000000..f3830e6
--- /dev/null
+++ b/log4j-catalog/log4j-catalog-war/src/main/webapp/css/app.css
@@ -0,0 +1,154 @@
+#nav {
+  text-align: center;
+  margin: 24px;
+}
+
+#nav a {
+  margin: 0 14px;
+}
+
+#ftr {
+  margin: 24px;
+  text-align: center;
+}
+
+.form-processing {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background-color: #fff;
+  z-index: 100;
+  opacity: .75;
+}
+
+.form-processing .gif {
+  position: absolute;
+  top: calc(50% - 16px);
+  left: calc(50% - 16px);
+  width: 32px;
+  height: 32px;
+  background-image: url(../images/ajax-loader.gif);
+  background-repeat: no-repeat;
+}
+
+.log4J-action-icon {
+  opacity: .4;
+}
+
+.log4j-catalog-form {
+  position: relative;
+}
+
+.log4j-catalog-form p {
+  position: relative;
+}
+
+.log4j-catalog-form input[type="text"],
+.log4j-catalog-form select,
+.log4j-catalog-form textarea {
+  width: 80%;
+  border: 1px solid #ddd;
+  padding: 2px 7px;
+  background-color: #fff;
+}
+
+.log4j-catalog-form select[multiple] {
+  height: 200px;
+}
+
+.log4j-catalog-form label {
+  display: block;
+  margin-bottom: 7px;
+  color: #aaa;
+}
+
+.log4j-catalog-form .form-error {
+  position: absolute;
+  top: 52px;
+  left: 354px;
+  color: #ff0000;
+  font-size: 12px;
+}
+
+.log4j-catalog-modal {
+  background-color: #fff;
+  border: 1px solid #ddd;
+  box-shadow: 0 0 20px #ccc;
+  left: 0;
+  margin: auto;
+  padding: 24px;
+  position: absolute;
+  right: 0;
+  top: 25%;
+  width: 500px;
+}
+
+.log4j-catalog-title {
+  border-bottom: 1px solid #ddd;
+  margin-bottom: 24px;
+  padding-bottom: 14px;
+}
+
+.log4j-catalog-button + .log4j-catalog-button {
+  margin-left: 24px;
+}
+
+/* Events */
+.event-attributes,
+.event-attribute-row {
+  font-size: 12px;
+}
+
+.event-attribute-row,
+.attribute-constraint-row,
+.product-event-row {
+  display: block;
+  clear: both;
+  line-height: 12px;
+  margin: 2px 0;
+  vertical-align: middle;
+}
+
+.event-attribute-row input[type="text"] {
+  width: 270px;
+  margin-right: 24px;
+}
+
+.event-attribute-item-required {
+  font-size: 10px;
+  color: #aaa;
+}
+
+.event-attribute-row button {
+  margin-left: 24px;
+}
+
+.attribute-constraint-row .form-error {
+  position: static;
+  padding: 0 4px;
+}
+
+.attribute-constraint-name {
+  font-size: 12px;
+  display: inline-block;
+  text-transform: uppercase;
+  width: 145px;
+}
+
+.attribute-constraint-data,
+#addAttributeConstraintValue {
+  width: 251px !important;
+}
+
+#addAttributeConstraintName {
+  width: 145px;
+}
+
+#addEventAttribute {
+  width: 375px !important;
+}
+
+#addEventAttributeButton,
+.remove-event-attribute-button {
+  cursor: pointer;
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/images/attributes.png
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/webapp/images/attributes.png 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/images/attributes.png
new file mode 100644
index 0000000..7957193
Binary files /dev/null and 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/images/attributes.png differ

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/images/constraint.png
----------------------------------------------------------------------
diff --git 
a/log4j-catalog/log4j-catalog-war/src/main/webapp/images/constraint.png 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/images/constraint.png
new file mode 100644
index 0000000..7604751
Binary files /dev/null and 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/images/constraint.png differ

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/js/app.js
----------------------------------------------------------------------
diff --git a/log4j-catalog/log4j-catalog-war/src/main/webapp/js/app.js 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/js/app.js
new file mode 100644
index 0000000..5fbb254
--- /dev/null
+++ b/log4j-catalog/log4j-catalog-war/src/main/webapp/js/app.js
@@ -0,0 +1,43 @@
+$(document).ready(function () {
+    // Clear localStorage
+    localStorage.clear();
+});
+
+// Modal action handlers
+function closeLog4jModal() {
+    $('.log4j-catalog-modal').remove();
+}
+
+function log4jSubmitHandler(submitHandler) {
+    submitHandler();
+    closeLog4jModal();
+}
+
+function showLog4JModal(title, content) {
+    closeLog4jModal();
+    var modalContent = ' \
+        <div class="log4j-catalog-modal"> \
+            <div class="log4j-catalog-title">' + title + '</div> \
+            <div class="log4j-catalog-content">' + content + '</div> \
+        </div>';
+
+    $('body').append(modalContent);
+    window.scrollTo(0, 0);
+}
+
+function showLoadingAnimation() {
+  $('.log4j-catalog-form').prepend('<div class="form-processing"><div 
class="gif"></div></div>');
+}
+
+function validateFormContent() {
+    var errors = 0;
+    $('.form-error').remove();
+    $('.required').each(function() {
+        if (!$(this).val()) {
+          errors++;
+          $('<span class="form-error">Required.</span>').insertAfter($(this));
+        }
+    });
+    if (errors) return false;
+    return true;
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-catalog/log4j-catalog-war/src/main/webapp/js/attributes.js
----------------------------------------------------------------------
diff --git a/log4j-catalog/log4j-catalog-war/src/main/webapp/js/attributes.js 
b/log4j-catalog/log4j-catalog-war/src/main/webapp/js/attributes.js
new file mode 100644
index 0000000..3b99e1e
--- /dev/null
+++ b/log4j-catalog/log4j-catalog-war/src/main/webapp/js/attributes.js
@@ -0,0 +1,348 @@
+$(document).ready(function () {
+    $('#AttributesTableContainer').jtable({
+        title: 'Table of Attributes',
+        paging: true, //Enable paging
+        pageSize: 25, //Set page size (default: 25)
+        sorting: true, //Enable sorting
+        defaultSorting: 'Name ASC', //Set default sorting
+        actions: {
+            listAction: 'api/attributes/list',
+        },
+        toolbar: {
+            items: [{
+                icon: 'js/jtable.2.4.0/themes/metro/add.png',
+                text: 'Add new record',
+                click: () => { addEditAttributeItem() }
+            }]
+        },
+        fields: {
+            id: {
+                key: true,
+                list: false
+            },
+            name: {
+                title: 'Name',
+                width: '15%'
+            },
+            displayName: {
+                title: 'Display Name',
+                width: '15%'
+            },
+            description: {
+                title: 'Description',
+                width: '25%'
+            },
+            dataType: {
+                title: 'Data Type',
+                width: '5%'
+            },
+            indexed: {
+                title: 'Indexed',
+                width: '5%',
+                display: function (attributeData) {
+                    return attributeData.record.indexed ? "true" : "false";
+                }
+            },
+            sortable: {
+                title: 'Sortable',
+                width: '5%',
+                display: function (attributeData) {
+                    return attributeData.record.sortable ? "true" : "false";
+                }
+            },
+            required: {
+                title: 'Required',
+                width: '5%',
+                display: function (attributeData) {
+                    return attributeData.record.required ? "true" : "false";
+                }
+            },
+            requestContext: {
+                title: 'RequestContext',
+                width: '3%',
+                display: function (attributeData) {
+                    return attributeData.record.requestContext ? "true" : 
"false";
+                }
+            },
+            constraints: {
+                title: 'Constraints',
+                width: '16%',
+                sorting: false,
+                edit: false,
+                create: false,
+                display: function (attributeData) {
+                    var constraintList = "";
+                    if (typeof(attributeData.record.constraints) != 
'undefined' && attributeData.record.constraints != null) {
+                        constraintList = 
attributeData.record.constraints.map(function (elem) {
+                            return elem.constraintType.name + '("' + 
elem.value + '")'
+                        }).join(" | ");
+                    }
+                    //Create a div that will be used to view associated 
attributes
+                    var $divConstraints = $('<div class="constraints">' + 
constraintList + '</div>');
+                    return $divConstraints;
+                }
+            },
+            edit: {
+                title: '',
+                width: '2%',
+                display: function (attributeData) {
+                    // Store attribute item data in localStorage
+                    var attributeDataItem = 
JSON.stringify(attributeData.record);
+                    localStorage.setItem('attributeItem' + 
attributeData.record.id,attributeDataItem);
+                    return '<img class="log4J-action-icon" 
src="js/jtable.2.4.0/themes/metro/edit.png" onClick="addEditAttributeItem(' + 
attributeData.record.id + ')" />';
+                }
+            },
+            delete: {
+                title: '',
+                width: '2%',
+                display: function (attributeData) {
+                    return '<img class="log4J-action-icon" 
src="js/jtable.2.4.0/themes/metro/delete.png" onClick="deleteAttributeItem(' + 
attributeData.record.id + ')" />';
+                }
+            }
+        }
+    });
+    $.ajax({
+        type: 'GET',
+        url: "/CatalogService/api/constraints/types",
+        success:function(response){
+            localStorage.setItem('allConstraints', response);
+        },
+        error:function(jqXhr, textStatus, errorThrown){
+            console.error(textStatus + " - " + errorThrown);
+        }
+    });
+    //Load attributes list from server
+    $('#AttributesTableContainer').jtable('load');
+});
+
+function deleteAttributeItem(attributeId) {
+    var response = confirm('Are you sure you want to delete this attribute?');
+    if (response) {
+        var postData = {};
+        postData['id'] = attributeId
+        $.ajax({
+            type: 'POST',
+            contentType: 'application/json',
+            url: 'api/attributes/delete',
+            data: JSON.stringify(postData),
+            success:function(response) {
+                if (response.Result === 'OK') {
+                    $('#AttributesTableContainer').jtable('load');
+                }
+            },
+            error:function(jqXhr, textStatus, errorThrown) {
+                console.error(textStatus + " - " + errorThrown);
+            }
+        });
+    }
+}
+
+function addEditattributeItemHandler() {
+  var validForm = validateFormContent();
+  if (validForm) {
+      showLoadingAnimation();
+      var postUrl = 'api/attributes/create';
+      var postData = {};
+      var attributeConstraints = [];
+      postData['name'] = $('#attributeName').val();
+      postData['displayName'] = $('#attributeDisplayName').val();
+      postData['description'] = $('#attributeDescription').val();
+      postData['dataType'] = $('#attributeDataType').val();
+      postData['indexed'] = $('#attributeIndexed').val();
+      postData['sortable'] = $('#attributeSortable').val();
+      postData['required'] = $('#attributeRequired').val();
+      postData['requestContext'] = $('#attributeRequestContext').val();
+      $('#attributeConstraints .attribute-constraint-row').each(function() {
+          var attributeConstraintItem = {
+              constraintType: { name: 
$(this).find('.attribute-constraint-name').text().toLowerCase() },
+              value: $(this).find('input')[0].value,
+          };
+          attributeConstraints.push(attributeConstraintItem);
+      });
+      postData['constraints'] = attributeConstraints;
+      if ($('#attributeId').val()) {
+          postUrl = 'api/attributes/update';
+          postData['id'] = $('#attributeId').val();
+      }
+      $.ajax({
+          type: 'POST',
+          contentType: 'application/json',
+          url: postUrl,
+          data: JSON.stringify(postData),
+          success:function(response) {
+              if (response.Result === 'OK') {
+                  $('#AttributesTableContainer').jtable('load');
+                  closeLog4jModal();
+              }
+          },
+          error:function(jqXhr, textStatus, errorThrown) {
+              console.error(textStatus + " - " + errorThrown);
+          }
+      });
+  }
+}
+
+function addEditAttributeItem(attributeId) {
+  var hiddenIdField = '';
+  var attributeData = {};
+  if (attributeId) {
+      hiddenIdField = '<input type="hidden" id="attributeId" name="id" 
value="' + attributeId + '" />';
+  } else {
+      attributeId = 'tempEventData';
+      var tempEventData = {
+          id: attributeId,
+          constraints: [],
+      }
+      localStorage.setItem('attributeItem' + attributeId, 
JSON.stringify(tempEventData));
+  }
+  attributeFormContent = ' \
+      <form id="add-edit-attribute-form" class="log4j-catalog-form" 
method="post"> \
+        ' + hiddenIdField + ' \
+        <p> \
+            <label>Name</label> \
+            <input type="text" id="attributeName" name="name" class="required" 
/> \
+        </p> \
+        <p> \
+            <label>Display Name</label> \
+            <input type="text" id="attributeDisplayName" name="displayName" 
class="required" /> \
+        </p> \
+        <p> \
+            <label>Description</label> \
+            <input type="text" id="attributeDescription" name="description" 
class="required" /> \
+        </p> \
+        <p> \
+            <label>Data Type</label> \
+            <select id="attributeDataType" name="indexed" class="required"> \
+            </select> \
+        </p> \
+        <p> \
+            <label>Indexed</label> \
+            <select id="attributeIndexed" name="indexed" class="required"> \
+                <option value="false">false</option> \
+                <option value="true">true</option> \
+            </select> \
+        </p> \
+        <p> \
+            <label>Sortable</label> \
+            <select id="attributeSortable" name="sortable" class="required"> \
+                <option value="false">false</option> \
+                <option value="true">true</option> \
+            </select> \
+        </p> \
+        <p> \
+            <label>Required</label> \
+            <select id="attributeRequired" name="required" class="required"> \
+                <option value="false">false</option> \
+                <option value="true">true</option> \
+            </select> \
+        </p> \
+        <p> \
+            <label>Request Context</label> \
+            <select id="attributeRequestContext" name="requestContext" 
class="required"> \
+                <option value="false">false</option> \
+                <option value="true">true</option> \
+            </select> \
+        </p> \
+        <p> \
+            <label>Assigned Constraints</label> \
+            <span id="attributeConstraints"></span> \
+        </p> \
+        <p> \
+            <label>Add Constraint</label> \
+            <span> \
+                <select name="addAttributeConstraintName" 
id="addAttributeConstraintName"> \
+                    <option value="">loading...</option> \
+                </select> \
+                <input type="text" name="addAttributeConstraintValue" 
id="addAttributeConstraintValue" /> \
+                <button id="addAttributeConstraintButton">+</button> \
+            </span> \
+        </p> \
+      </form> \
+      <div class="log4j-catalog-button-row"> \
+          <button class="log4j-catalog-button" 
onclick="closeLog4jModal()">Cancel</button>\
+          <button class="log4j-catalog-button" 
onclick="addEditattributeItemHandler()">Save</button> \
+      </div> \
+  ';
+  showLog4JModal('Add / Edit Attribute Item', attributeFormContent);
+  var dataTypes = ['STRING', 'BIG_DECIMAL', 'DOUBLE', 'FLOAT', 'INT', 'LONG', 
'BOOLEAN', 'LIST', 'MAP'];
+  $.each(dataTypes.sort(), function(index, value) {
+      $('#attributeDataType').append('<option value="' + value + '">' + value 
+ '</option>');
+  });
+  if (localStorage.getItem('attributeItem' + attributeId)) {
+      attributeData = JSON.parse(localStorage.getItem('attributeItem' + 
attributeId));
+      $('#attributeName').val(attributeData.name);
+      $('#attributeDisplayName').val(attributeData.displayName);
+      $('#attributeDescription').val(attributeData.description);
+      $('#attributeDataType option[value="' + attributeData.dataType + 
'"]').attr('selected', 'selected');
+      $('#attributeIndexed option[value="' + attributeData.indexed + 
'"]').attr('selected', 'selected');
+      $('#attributeSortable option[value="' + attributeData.sortable + 
'"]').attr('selected', 'selected');
+      $('#attributeRequired option[value="' + attributeData.required + 
'"]').attr('selected', 'selected');
+      $('#attributeRequestContext option[value="' + 
attributeData.requestContext + '"]').attr('selected', 'selected');
+  }
+  populateAttributeConstraints(attributeData.constraints, attributeId);
+}
+
+function populateAttributeConstraints(assignedConstraints, attributeId) {
+    var selectedConstraints = [];
+    $('#attributeConstraints').children().remove();
+    if (attributeId && assignedConstraints) {
+        assignedConstraints.map((item) => {
+            selectedConstraints.push(item.constraintType.name);
+            $('#attributeConstraints').append(' \
+                <span class="attribute-constraint-row"> \
+                    <span class="attribute-constraint-name">' + 
item.constraintType.name + '</span> \
+                    <input type="text" name="constraints[]" 
class="attribute-constraint-data required" value="' + item.value + '" /> \
+                    <button class="remove-attribute-constraint-button" alt="' 
+ attributeId + '" rel="' + item.constraintType.name + '">-</button> \
+                </span> \
+            ');
+        });
+    }
+    function checkPendingRequest() {
+        if ($.active > 0) {
+            window.setTimeout(checkPendingRequest, 1000);
+        } else {
+            var allConstraints = 
localStorage.getItem('allConstraints').split(',');
+            allConstraints.sort();
+            $('#addAttributeConstraintName option').remove();
+            allConstraints.map((item) => {
+                if (!selectedConstraints.includes(item)) {
+                    $('#addAttributeConstraintName').append(' \
+                        <option value="' + item + '">' + item.toUpperCase() + 
'</option> \
+                    ');
+                }
+            });
+        }
+    }
+    checkPendingRequest();
+    assignAttributeConstraintListeners(attributeId);
+}
+
+function assignAttributeConstraintListeners(attributeId) {
+    $('#addAttributeConstraintButton, 
.remove-attribute-constraint-button').unbind();
+    $('#addAttributeConstraintButton').click(function(e) {
+        e.preventDefault();
+        var allConstraints = localStorage.getItem('allConstraints').split(',');
+        attributeData = JSON.parse(localStorage.getItem('attributeItem' + 
attributeId));
+        if (typeof(attributeData.constraints) == 'undefined' || 
attributeData.constraints == null) {
+            attributeData.constraints = [];
+        }
+        attributeData.constraints.push({
+            constraintType: { name: $('#addAttributeConstraintName').val() },
+            value: $('#addAttributeConstraintValue').val()
+        });
+        localStorage.setItem('attributeItem' + attributeId, 
JSON.stringify(attributeData));
+        $('#addAttributeConstraintValue').val('');
+        populateAttributeConstraints(attributeData.constraints, attributeId);
+    });
+    $('.remove-attribute-constraint-button').click(function(e) {
+        e.preventDefault();
+        var allConstraints = localStorage.getItem('allConstraints').split(',');
+        attributeData = JSON.parse(localStorage.getItem('attributeItem' + 
attributeId));
+        var newConstraints = attributeData.constraints.filter((obj) => {
+            return obj.constraintType.name !== $(this).attr('rel');
+        });
+        attributeData['constraints'] = newConstraints;
+        localStorage.setItem('attributeItem' + attributeId, 
JSON.stringify(attributeData));
+        populateAttributeConstraints(attributeData.constraints, attributeId);
+    });
+}

Reply via email to