bug[ats_ATS302825]: NR Alpha - Search by id is loading slower than release

   - Move AtsAdmin to AtsConfigurations rest call
   - Move WorkDef loading to AtsConfigurations
   - Move AtsUser cache to AtsConfigurations
   - Move Valid State Loading to AtsConfig and AtsConfigurations
   - Remove need for separete valid state Artifact
   - Improve loading of ATS Config Objects

Change-Id: I3c2119778c135678306e4464f18c4ab023823ab1
diff --git a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/IAtsServices.java b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/IAtsServices.java
index 2edb2a3..7be48f0 100644
--- a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/IAtsServices.java
+++ b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/IAtsServices.java
@@ -15,6 +15,7 @@
 import org.eclipse.osee.ats.api.config.AtsConfigurations;
 import org.eclipse.osee.ats.api.config.IAtsCache;
 import org.eclipse.osee.ats.api.config.IAtsConfigurationProvider;
+import org.eclipse.osee.ats.api.config.IWorkDefinitionStringProvider;
 import org.eclipse.osee.ats.api.ev.IAtsEarnedValueService;
 import org.eclipse.osee.ats.api.ev.IAtsEarnedValueServiceProvider;
 import org.eclipse.osee.ats.api.program.IAtsProgramService;
@@ -50,7 +51,7 @@
 /**
  * @author Donald G. Dunne
  */
-public interface IAtsServices extends IAtsConfigurationProvider {
+public interface IAtsServices extends IAtsConfigurationProvider, IWorkDefinitionStringProvider {
 
    IRelationResolver getRelationResolver();
 
@@ -133,6 +134,9 @@
 
    IAtsActionFactory getActionFactory();
 
+   /**
+    * @param key - key of key/value config pair.  equals sign not accepted
+    */
    String getConfigValue(String key);
 
    Log getLogger();
@@ -143,4 +147,6 @@
 
    <T> T getConfigItem(Long uuid);
 
+   void setConfigValue(String key, String value);
+
 }
diff --git a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/config/AtsConfigurations.java b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/config/AtsConfigurations.java
index fb51505..97d7582 100644
--- a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/config/AtsConfigurations.java
+++ b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/config/AtsConfigurations.java
@@ -11,23 +11,31 @@
 package org.eclipse.osee.ats.api.config;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import javax.xml.bind.annotation.XmlRootElement;
+import org.codehaus.jackson.annotate.JsonIgnore;
 import org.eclipse.osee.ats.api.user.JaxAtsUser;
 import org.eclipse.osee.ats.api.util.ColorColumns;
+import org.eclipse.osee.framework.jdk.core.util.Collections;
+import org.eclipse.osee.framework.jdk.core.util.Strings;
 
 /**
  * @author Donald G. Dunne
  */
 @XmlRootElement
-public class AtsConfigurations {
+public class AtsConfigurations implements IWorkDefinitionStringProvider {
 
-   private final List<AtsConfiguration> configs = new ArrayList<>();
+   private List<AtsConfiguration> configs = new ArrayList<>();
    private AtsViews views = new AtsViews();
    private ColorColumns colorColumns = new ColorColumns();
    List<JaxAtsUser> users = new ArrayList<>();
-   List<JaxAtsUser> atsAdmins = new ArrayList<>();
-   List<Integer> atsActiveConfigIds = new ArrayList<>();
+   List<Long> atsAdmins = new ArrayList<>();
+   List<Long> atsConfigIds = new ArrayList<>();
+   private Collection<String> validStateNames = new ArrayList<>();
+   private Map<String, String> workDefIdToWorkDef = new HashMap<>();
 
    public List<AtsConfiguration> getConfigs() {
       return configs;
@@ -57,16 +65,59 @@
       this.users = users;
    }
 
-   public List<JaxAtsUser> getAtsAdmins() {
+   public String getAtsConfigIdsStr() {
+      return Collections.toString(",", atsConfigIds);
+   }
+
+   @JsonIgnore
+   public List<Long> getAtsConfigIds() {
+      return atsConfigIds;
+   }
+
+   public void setAtsConfigIdsStr(String atsConfigIdsStr) {
+      parseStringOfLongs(this.atsConfigIds, atsConfigIdsStr);
+   }
+
+   public Collection<String> getValidStateNames() {
+      return validStateNames;
+   }
+
+   public void setConfigs(List<AtsConfiguration> configs) {
+      this.configs = configs;
+   }
+
+   public void setValidStateNames(Collection<String> validStateNames) {
+      this.validStateNames = validStateNames;
+   }
+
+   public String getAtsAdminsStr() {
+      return Collections.toString(",", atsAdmins);
+   }
+
+   @JsonIgnore
+   public List<Long> getAtsAdmins() {
       return atsAdmins;
    }
 
-   public List<Integer> getAtsActiveConfigIds() {
-      return atsActiveConfigIds;
+   public void setAtsAdminsStr(String atsAdmins) {
+      parseStringOfLongs(this.atsAdmins, atsAdmins);
    }
 
-   public void setAtsActiveConfigIds(List<Integer> atsActiveConfigIds) {
-      this.atsActiveConfigIds = atsActiveConfigIds;
+   private void parseStringOfLongs(List<Long> uuids, String strOfLongs) {
+      if (Strings.isValid(strOfLongs)) {
+         for (String uuid : strOfLongs.split(",")) {
+            uuids.add(Long.valueOf(uuid));
+         }
+      }
+   }
+
+   @Override
+   public Map<String, String> getWorkDefIdToWorkDef() {
+      return workDefIdToWorkDef;
+   }
+
+   public void setWorkDefIdToWorkDef(Map<String, String> workDefIdToWorkDef) {
+      this.workDefIdToWorkDef = workDefIdToWorkDef;
    }
 
 }
diff --git a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/config/IWorkDefinitionStringProvider.java b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/config/IWorkDefinitionStringProvider.java
new file mode 100644
index 0000000..b33160a
--- /dev/null
+++ b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/config/IWorkDefinitionStringProvider.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.ats.api.config;
+
+import java.util.Map;
+
+/**
+ * @author Donald G. Dunne
+ */
+public interface IWorkDefinitionStringProvider {
+
+   public Map<String, String> getWorkDefIdToWorkDef();
+
+}
diff --git a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/data/AtsArtifactToken.java b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/data/AtsArtifactToken.java
index ff89eb7..736dd09 100644
--- a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/data/AtsArtifactToken.java
+++ b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/data/AtsArtifactToken.java
@@ -45,8 +45,6 @@
       "Web Programs", CoreArtifactTypes.UniversalGroup);
    public static IArtifactToken EVReportPrograms = TokenFactory.createArtifactToken(8174118, "ABPMYxe8_1EZYA8obTQA",
       "EV Report Programs", CoreArtifactTypes.UniversalGroup);
-   public static IArtifactToken WorkDef_State_Names = TokenFactory.createArtifactToken(1330130, "BFqfTrN8W3QmQSFAi6wA",
-      "WorkDef_State_Names", CoreArtifactTypes.GeneralData);
    public static IArtifactToken AtsAdmin =
       TokenFactory.createArtifactToken(136750, "AAABHaItoVsAG6ZAAMyhQw", "AtsAdmin", CoreArtifactTypes.UserGroup);
    public static IArtifactToken AtsTempAdmin =
diff --git a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/workdef/IAtsWorkDefinitionService.java b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/workdef/IAtsWorkDefinitionService.java
index cda36dd..d8923c7 100644
--- a/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/workdef/IAtsWorkDefinitionService.java
+++ b/plugins/org.eclipse.osee.ats.api/src/org/eclipse/osee/ats/api/workdef/IAtsWorkDefinitionService.java
@@ -13,6 +13,7 @@
 import java.util.Collection;
 import java.util.List;
 import org.eclipse.osee.ats.api.IAtsWorkItem;
+import org.eclipse.osee.ats.api.config.IWorkDefinitionStringProvider;
 import org.eclipse.osee.framework.core.util.XResultData;
 import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
 
@@ -52,8 +53,10 @@
 
    Collection<IAtsWorkDefinition> getAllWorkDefinitions(XResultData resultData) throws OseeCoreException, Exception;
 
-   Collection<String> getAllValidStateNames(XResultData resultData) throws Exception;
+   Collection<String> getAllValidStateNames(XResultData resultData);
 
    List<IAtsRuleDefinition> getRuleDefinitions();
 
+   void setWorkDefinitionStringProvider(IWorkDefinitionStringProvider workDefinitionStringProvider);
+
 }
diff --git a/plugins/org.eclipse.osee.ats.core.client/OSGI-INF/ats.client.service.xml b/plugins/org.eclipse.osee.ats.core.client/OSGI-INF/ats.client.service.xml
index 2f4e8aa..d94eb1d 100644
--- a/plugins/org.eclipse.osee.ats.core.client/OSGI-INF/ats.client.service.xml
+++ b/plugins/org.eclipse.osee.ats.core.client/OSGI-INF/ats.client.service.xml
@@ -10,4 +10,5 @@
    <reference bind="setLogger" cardinality="1..1" interface="org.eclipse.osee.logger.Log" name="Log" policy="static"/>
    <reference bind="addSearchDataProvider" cardinality="0..n" interface="org.eclipse.osee.ats.api.query.IAtsSearchDataProvider" name="IAtsSearchDataProvider" policy="dynamic" unbind="removeSearchDataProvider"/>
    <reference bind="setConfigurationsService" cardinality="1..1" interface="org.eclipse.osee.ats.api.config.IAtsConfigurationProvider" name="IAtsConfigurationProvider" policy="static"/>
+   <reference bind="setAtsUserService" cardinality="1..1" interface="org.eclipse.osee.ats.core.client.IAtsUserServiceClient" name="IAtsUserServiceClient" policy="static"/>
 </scr:component>
diff --git a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsClient.java b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsClient.java
index d0f8693..ef51c13 100644
--- a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsClient.java
+++ b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsClient.java
@@ -119,8 +119,6 @@
 
    TeamWorkflowProviders getTeamWorkflowProviders();
 
-   void setConfigValue(String key, String value);
-
    List<IAtsSearchDataProvider> getSearchDataProviders();
 
    IAtsEventService getEventService();
diff --git a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsUserServiceClient.java b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsUserServiceClient.java
index 770981e..811610a 100644
--- a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsUserServiceClient.java
+++ b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/IAtsUserServiceClient.java
@@ -14,6 +14,7 @@
 import java.util.List;
 import org.eclipse.osee.ats.api.IAtsWorkItem;
 import org.eclipse.osee.ats.api.user.IAtsUser;
+import org.eclipse.osee.ats.api.user.IAtsUserService;
 import org.eclipse.osee.framework.core.data.IUserToken;
 import org.eclipse.osee.framework.core.enums.Active;
 import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
@@ -23,7 +24,7 @@
 /**
  * @author Donald G. Dunne
  */
-public interface IAtsUserServiceClient {
+public interface IAtsUserServiceClient extends IAtsUserService {
 
    User getOseeUser(IAtsUser user) throws OseeCoreException;
 
diff --git a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/artifact/AtsArtifactChecks.java b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/artifact/AtsArtifactChecks.java
index f48f398..4ce272a 100644
--- a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/artifact/AtsArtifactChecks.java
+++ b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/artifact/AtsArtifactChecks.java
@@ -27,7 +27,7 @@
 import org.eclipse.osee.ats.core.client.internal.Activator;
 import org.eclipse.osee.ats.core.client.internal.AtsClientService;
 import org.eclipse.osee.ats.core.client.search.UserRelatedToAtsObjectSearch;
-import org.eclipse.osee.ats.core.client.util.AtsGroup;
+import org.eclipse.osee.ats.core.client.util.AtsUtilClient;
 import org.eclipse.osee.ats.core.client.workflow.AbstractWorkflowArtifact;
 import org.eclipse.osee.ats.core.util.AtsUtilCore;
 import org.eclipse.osee.framework.core.data.IRelationType;
@@ -53,7 +53,7 @@
    @Override
    public IStatus isDeleteableRelation(Artifact artifact, IRelationType relationType) throws OseeCoreException {
       if (deletionChecksEnabled) {
-         boolean isAtsAdmin = AtsGroup.AtsAdmin.isCurrentUserMember();
+         boolean isAtsAdmin = AtsUtilClient.isAtsAdmin();
          if (!isAtsAdmin && Admin_Only_Relation_Type_Ids.contains(relationType.getGuid())) {
             return createStatus(
                String.format("Deletion of relation type [%s] off artifact [%s] is only permitted by ATS Admin",
@@ -65,7 +65,7 @@
 
    @Override
    public IStatus isDeleteable(Collection<Artifact> artifacts) throws OseeCoreException {
-      boolean isAtsAdmin = AtsGroup.AtsAdmin.isCurrentUserMember();
+      boolean isAtsAdmin = AtsUtilClient.isAtsAdmin();
 
       IStatus result = Status.OK_STATUS;
 
diff --git a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/AtsClientImpl.java b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/AtsClientImpl.java
index 172a223..563e86c 100644
--- a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/AtsClientImpl.java
+++ b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/AtsClientImpl.java
@@ -12,6 +12,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.logging.Level;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -79,7 +80,6 @@
 import org.eclipse.osee.ats.core.client.internal.query.AtsQueryServiceImpl;
 import org.eclipse.osee.ats.core.client.internal.review.AtsReviewServiceImpl;
 import org.eclipse.osee.ats.core.client.internal.store.AtsVersionServiceImpl;
-import org.eclipse.osee.ats.core.client.internal.user.AtsUserServiceClientImpl;
 import org.eclipse.osee.ats.core.client.internal.workdef.ArtifactResolverImpl;
 import org.eclipse.osee.ats.core.client.internal.workflow.AtsAttributeResolverServiceImpl;
 import org.eclipse.osee.ats.core.client.internal.workflow.AtsRelationResolverServiceImpl;
@@ -121,7 +121,6 @@
 import org.eclipse.osee.framework.plugin.core.util.Jobs;
 import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
 import org.eclipse.osee.framework.skynet.core.artifact.ArtifactTypeManager;
-import org.eclipse.osee.framework.skynet.core.artifact.Attribute;
 import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery;
 import org.eclipse.osee.jdbc.JdbcService;
 import org.eclipse.osee.logger.Log;
@@ -141,7 +140,6 @@
    private IVersionFactory versionFactory;
    private AtsWorkDefinitionCache workDefCache;
    private IAtsEarnedValueService earnedValueService;
-   private IAtsUserService userService;
    private IAtsUserServiceClient userServiceClient;
    private IAtsWorkItemService workItemService;
    private IAtsBranchService branchService;
@@ -194,6 +192,10 @@
       this.configProvider = configProvider;
    }
 
+   public void setAtsUserService(IAtsUserServiceClient userServiceClient) {
+      this.userServiceClient = userServiceClient;
+   }
+
    public void addSearchDataProvider(IAtsSearchDataProvider provider) {
       searchDataProviders.add(provider);
    }
@@ -205,9 +207,6 @@
    public void start() throws OseeCoreException {
       Conditions.checkNotNull(workDefService, "IAtsWorkDefinitionService");
 
-      userService = new AtsUserServiceClientImpl(this);
-      userServiceClient = (IAtsUserServiceClient) userService;
-
       atsCache = new AtsCache(this);
       earnedValueService = new AtsEarnedValueImpl(logger, getServices());
 
@@ -220,12 +219,15 @@
       versionFactory = new VersionFactory();
 
       workDefCache = new AtsWorkDefinitionCache();
+
       artifactResolver = new ArtifactResolverImpl(this);
       teamWorkflowProvidersLazy = new TeamWorkflowProviders();
       workItemService = new AtsWorkItemServiceImpl(this, teamWorkflowProvidersLazy);
       attributeResolverService = new AtsAttributeResolverServiceImpl();
       relationResolver = new AtsRelationResolverServiceImpl(this);
 
+      workDefService.setWorkDefinitionStringProvider(this);
+
       workDefAdmin = new AtsWorkDefinitionAdminImpl(workDefCache, workDefService, attributeResolverService,
          teamWorkflowProvidersLazy);
       branchService = new AtsBranchServiceImpl(this, teamWorkflowProvidersLazy);
@@ -344,11 +346,16 @@
          @Override
          public void run() {
             try {
-               List<Artifact> artifacts = ArtifactQuery.getArtifactListFromIds(
-                  configProvider.getConfigurations().getAtsActiveConfigIds(), AtsUtilCore.getAtsBranch());
-
+               List<Integer> ids = new LinkedList<>();
+               for (Long id : configProvider.getConfigurations().getAtsConfigIds()) {
+                  ids.add(id.intValue());
+               }
+               List<Artifact> artifacts = ArtifactQuery.getArtifactListFromIds(ids, AtsUtilCore.getAtsBranch());
                for (Artifact artifact : artifacts) {
-                  atsCache.cacheArtifact(artifact);
+                  IAtsConfigObject configObj = configItemFactory.getConfigObject(artifact);
+                  if (configObj != null) {
+                     atsCache.cacheAtsObject(configObj);
+                  }
                }
             } catch (Exception ex) {
                OseeLog.log(Activator.class, Level.SEVERE, ex);
@@ -422,7 +429,7 @@
 
    @Override
    public IAtsUserService getUserService() throws OseeStateException {
-      return userService;
+      return userServiceClient;
    }
 
    private IAtsCache atsCache() throws OseeCoreException {
@@ -563,29 +570,6 @@
       return result;
    }
 
-   @SuppressWarnings("deprecation")
-   @Override
-   public void setConfigValue(String key, String value) {
-      Artifact atsConfig = ArtifactQuery.getArtifactFromToken(AtsArtifactToken.AtsConfig, AtsUtilCore.getAtsBranch());
-      if (atsConfig != null) {
-         String keyValue = String.format("%s=%s", key, value);
-         boolean found = false;
-         List<Attribute<String>> attributes = atsConfig.getAttributes(CoreAttributeTypes.GeneralStringData);
-         for (Attribute<String> attr : attributes) {
-            String str = attr.getValue();
-            if (str.startsWith(key)) {
-               attr.setValue(keyValue);
-               found = true;
-               break;
-            }
-         }
-         if (!found) {
-            atsConfig.addAttribute(CoreAttributeTypes.GeneralStringData, keyValue);
-         }
-         atsConfig.persist(String.format("Update AtsConfig [%s] Key", key));
-      }
-   }
-
    @Override
    public IAtsServices getServices() {
       return this;
diff --git a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/user/AtsUserServiceClientImpl.java b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/user/AtsUserServiceClientImpl.java
index 846d6ac..8f05b81 100644
--- a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/user/AtsUserServiceClientImpl.java
+++ b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/internal/user/AtsUserServiceClientImpl.java
@@ -21,7 +21,6 @@
 import org.eclipse.osee.ats.api.user.IAtsUser;
 import org.eclipse.osee.ats.api.user.JaxAtsUser;
 import org.eclipse.osee.ats.core.client.IAtsUserServiceClient;
-import org.eclipse.osee.ats.core.client.util.AtsGroup;
 import org.eclipse.osee.ats.core.users.AbstractAtsUserService;
 import org.eclipse.osee.ats.core.util.AtsUtilCore;
 import org.eclipse.osee.framework.core.enums.Active;
@@ -46,10 +45,6 @@
       // For OSGI Instantiation
    }
 
-   public AtsUserServiceClientImpl(IAtsConfigurationProvider configurationProvider) {
-      this.configurationProvider = configurationProvider;
-   }
-
    public void setConfigurationsService(IAtsConfigurationProvider configurationProvider) {
       this.configurationProvider = configurationProvider;
    }
@@ -148,12 +143,7 @@
 
    @Override
    public boolean isAtsAdmin(IAtsUser user) {
-      Boolean admin = userIdToAdmin.get(user.getUserId());
-      if (admin == null) {
-         admin = AtsGroup.AtsAdmin.isMember(user);
-         userIdToAdmin.put(user.getUserId(), admin);
-      }
-      return admin;
+      return configurationProvider.getConfigurations().getAtsAdmins().contains(user.getUuid());
    }
 
    @Override
diff --git a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/util/AtsUtilClient.java b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/util/AtsUtilClient.java
index 626484e..c0b8e7a 100644
--- a/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/util/AtsUtilClient.java
+++ b/plugins/org.eclipse.osee.ats.core.client/src/org/eclipse/osee/ats/core/client/util/AtsUtilClient.java
@@ -21,6 +21,7 @@
 import org.eclipse.osee.ats.api.workdef.ITransitionResult;
 import org.eclipse.osee.ats.api.workflow.transition.TransitionResults;
 import org.eclipse.osee.ats.core.client.internal.Activator;
+import org.eclipse.osee.ats.core.client.internal.AtsClientService;
 import org.eclipse.osee.ats.core.util.AtsUtilCore;
 import org.eclipse.osee.framework.core.data.IArtifactToken;
 import org.eclipse.osee.framework.core.enums.Active;
@@ -121,7 +122,8 @@
    public static boolean isAtsAdmin() {
       if (atsAdmin == null) {
          try {
-            atsAdmin = AtsGroup.AtsAdmin.isCurrentUserMember();
+            atsAdmin = AtsClientService.get().getConfigurations().getAtsAdmins().contains(
+               AtsClientService.get().getUserService().getCurrentUser().getUuid());
          } catch (OseeCoreException ex) {
             OseeLog.log(Activator.class, Level.SEVERE, ex);
             atsAdmin = false;
diff --git a/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/users/AbstractAtsUserService.java b/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/users/AbstractAtsUserService.java
index 90d9433..f32be96 100644
--- a/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/users/AbstractAtsUserService.java
+++ b/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/users/AbstractAtsUserService.java
@@ -31,7 +31,6 @@
 public abstract class AbstractAtsUserService implements IAtsUserService {
 
    protected final Map<String, IAtsUser> userIdToAtsUser = new ConcurrentHashMap<>(300);
-   protected final Map<String, Boolean> userIdToAdmin = new ConcurrentHashMap<>(300);
    protected final Map<String, IAtsUser> nameToAtsUser = new ConcurrentHashMap<>(300);
    protected IAtsUser currentUser = null;
 
@@ -144,7 +143,6 @@
 
    @Override
    public void reloadCache() {
-      userIdToAdmin.clear();
       userIdToAtsUser.clear();
       nameToAtsUser.clear();
       currentUser = null;
diff --git a/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/util/AtsCoreServiceImpl.java b/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/util/AtsCoreServiceImpl.java
index 4e212e9..fb0a875 100644
--- a/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/util/AtsCoreServiceImpl.java
+++ b/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/util/AtsCoreServiceImpl.java
@@ -10,14 +10,20 @@
  *******************************************************************************/
 package org.eclipse.osee.ats.core.util;
 
+import java.util.Collection;
+import java.util.Map;
 import org.eclipse.osee.ats.api.IAtsConfigObject;
 import org.eclipse.osee.ats.api.IAtsObject;
 import org.eclipse.osee.ats.api.IAtsServices;
+import org.eclipse.osee.ats.api.data.AtsArtifactToken;
 import org.eclipse.osee.ats.api.data.AtsAttributeTypes;
+import org.eclipse.osee.ats.api.util.IAtsChangeSet;
 import org.eclipse.osee.ats.api.workdef.IAtsWorkDefinitionAdmin;
 import org.eclipse.osee.ats.api.workdef.IAttributeResolver;
+import org.eclipse.osee.ats.api.workflow.IAttribute;
 import org.eclipse.osee.framework.core.data.ArtifactId;
 import org.eclipse.osee.framework.core.data.IArtifactToken;
+import org.eclipse.osee.framework.core.enums.CoreAttributeTypes;
 import org.eclipse.osee.framework.jdk.core.util.Conditions;
 
 /**
@@ -85,4 +91,34 @@
       return atsObject;
    }
 
+   @Override
+   public void setConfigValue(String key, String value) {
+      ArtifactId atsConfig = getArtifact(AtsArtifactToken.AtsConfig);
+      IAtsChangeSet changes =
+         getStoreService().createAtsChangeSet("Set AtsConfig Value", getUserService().getCurrentUser());
+      if (atsConfig != null) {
+         String keyValue = String.format("%s=%s", key, value);
+         boolean found = false;
+         Collection<IAttribute<Object>> attributes =
+            getAttributeResolver().getAttributes(atsConfig, CoreAttributeTypes.GeneralStringData);
+         for (IAttribute<Object> attr : attributes) {
+            String str = (String) attr.getValue();
+            if (str.startsWith(key)) {
+               changes.setAttribute(atsConfig, attr.getId(), keyValue);
+               found = true;
+               break;
+            }
+         }
+         if (!found) {
+            changes.addAttribute(atsConfig, CoreAttributeTypes.GeneralStringData, keyValue);
+         }
+         changes.executeIfNeeded();
+      }
+   }
+
+   @Override
+   public Map<String, String> getWorkDefIdToWorkDef() {
+      return getConfigurations().getWorkDefIdToWorkDef();
+   }
+
 }
diff --git a/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/workdef/AtsWorkDefinitionCache.java b/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/workdef/AtsWorkDefinitionCache.java
index 0397c5f..f28268c 100644
--- a/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/workdef/AtsWorkDefinitionCache.java
+++ b/plugins/org.eclipse.osee.ats.core/src/org/eclipse/osee/ats/core/workdef/AtsWorkDefinitionCache.java
@@ -63,4 +63,10 @@
       workDefIdToWorkDefintion.clear();
    }
 
+   public void cache(String id, IAtsWorkDefinition workDef) {
+      WorkDefinitionMatch match = new WorkDefinitionMatch(id, null);
+      match.setWorkDefinition(workDef);
+      workDefIdToWorkDefintion.put(id, match);
+   }
+
 }
diff --git a/plugins/org.eclipse.osee.ats.dsl.integration/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.ats.dsl.integration/META-INF/MANIFEST.MF
index d159de0..265e176 100644
--- a/plugins/org.eclipse.osee.ats.dsl.integration/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.osee.ats.dsl.integration/META-INF/MANIFEST.MF
@@ -10,6 +10,7 @@
 Import-Package: org.eclipse.emf.common.util,
  org.eclipse.emf.ecore,
  org.eclipse.osee.ats.api,
+ org.eclipse.osee.ats.api.config,
  org.eclipse.osee.ats.api.review,
  org.eclipse.osee.ats.api.rule,
  org.eclipse.osee.ats.api.team,
diff --git a/plugins/org.eclipse.osee.ats.dsl.integration/src/org/eclipse/osee/ats/dsl/integration/internal/AtsWorkDefinitionServiceImpl.java b/plugins/org.eclipse.osee.ats.dsl.integration/src/org/eclipse/osee/ats/dsl/integration/internal/AtsWorkDefinitionServiceImpl.java
index 2a6904e..09b1b4d 100644
--- a/plugins/org.eclipse.osee.ats.dsl.integration/src/org/eclipse/osee/ats/dsl/integration/internal/AtsWorkDefinitionServiceImpl.java
+++ b/plugins/org.eclipse.osee.ats.dsl.integration/src/org/eclipse/osee/ats/dsl/integration/internal/AtsWorkDefinitionServiceImpl.java
@@ -14,9 +14,11 @@
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.logging.Level;
 import org.eclipse.osee.ats.api.IAtsWorkItem;
+import org.eclipse.osee.ats.api.config.IWorkDefinitionStringProvider;
 import org.eclipse.osee.ats.api.review.IAtsAbstractReview;
 import org.eclipse.osee.ats.api.user.IAtsUserService;
 import org.eclipse.osee.ats.api.workdef.IAtsCompositeLayoutItem;
@@ -53,6 +55,7 @@
    private IAttributeResolver attrResolver;
    private IAtsUserService userService;
    private Log logger;
+   private IWorkDefinitionStringProvider workDefinitionStringProvider;
 
    public void setLogger(Log logger) {
       this.logger = logger;
@@ -115,7 +118,13 @@
    @Override
    public IAtsWorkDefinition getWorkDef(String workDefId, XResultData resultData) throws Exception {
       Conditions.checkNotNullOrEmpty(workDefId, "workDefId");
-      String workDefStr = workDefStore.loadWorkDefinitionString(workDefId);
+      String workDefStr = null;
+      if (workDefinitionStringProvider != null && workDefinitionStringProvider.getWorkDefIdToWorkDef() != null) {
+         workDefStr = workDefinitionStringProvider.getWorkDefIdToWorkDef().get(workDefId);
+      }
+      if (workDefStr == null) {
+         workDefStr = workDefStore.loadWorkDefinitionString(workDefId);
+      }
       Conditions.checkNotNullOrEmpty(workDefStr, "workDefStr");
       AtsDsl atsDsl = ModelUtil.loadModel(workDefId + ".ats", workDefStr);
       ConvertAtsDslToWorkDefinition convert =
@@ -253,23 +262,39 @@
    }
 
    @Override
-   public Collection<IAtsWorkDefinition> getAllWorkDefinitions(XResultData resultData) throws Exception {
+   public Collection<IAtsWorkDefinition> getAllWorkDefinitions(XResultData resultData) {
       List<IAtsWorkDefinition> workDefs = new ArrayList<>();
-      for (Pair<String, String> entry : workDefStore.getWorkDefinitionStrings()) {
-         String name = entry.getFirst();
-         String workDefStr = entry.getSecond();
+      if (workDefinitionStringProvider != null && workDefinitionStringProvider.getWorkDefIdToWorkDef() != null) {
+         for (Entry<String, String> entry : workDefinitionStringProvider.getWorkDefIdToWorkDef().entrySet()) {
+            String name = entry.getKey();
+            String workDefStr = entry.getValue();
+            processWorkDef(resultData, workDefs, name, workDefStr);
+         }
+      } else {
+         for (Pair<String, String> entry : workDefStore.getWorkDefinitionStrings()) {
+            String name = entry.getFirst();
+            String workDefStr = entry.getSecond();
+            processWorkDef(resultData, workDefs, name, workDefStr);
+         }
+      }
+      return workDefs;
+   }
+
+   private void processWorkDef(XResultData resultData, List<IAtsWorkDefinition> workDefs, String name, String workDefStr) {
+      try {
          AtsDsl atsDsl = ModelUtil.loadModel(name + ".ats", workDefStr);
          ConvertAtsDslToWorkDefinition convert =
             new ConvertAtsDslToWorkDefinition(name, atsDsl, resultData, attrResolver, userService);
          for (IAtsWorkDefinition workDef : convert.convert()) {
             workDefs.add(workDef);
          }
+      } catch (Exception ex) {
+         throw new OseeCoreException(ex);
       }
-      return workDefs;
    }
 
    @Override
-   public Collection<String> getAllValidStateNames(XResultData resultData) throws Exception {
+   public Collection<String> getAllValidStateNames(XResultData resultData) {
       Set<String> allValidStateNames = new HashSet<>();
       for (IAtsWorkDefinition workDef : getAllWorkDefinitions(resultData)) {
          for (String stateName : getStateNames(workDef)) {
@@ -281,4 +306,9 @@
       return allValidStateNames;
    }
 
+   @Override
+   public void setWorkDefinitionStringProvider(IWorkDefinitionStringProvider workDefinitionStringProvider) {
+      this.workDefinitionStringProvider = workDefinitionStringProvider;
+   }
+
 }
diff --git a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/AtsServerImpl.java b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/AtsServerImpl.java
index 114c5e5..00cd0d6 100644
--- a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/AtsServerImpl.java
+++ b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/AtsServerImpl.java
@@ -226,6 +226,7 @@
       relationResolver = new AtsRelationResolverServiceImpl(this);
       attributeResolverService.setOrcsApi(orcsApi);
       atsCache = new AtsCache(this);
+      workDefService.setWorkDefinitionStringProvider(this);
       workDefAdmin = new AtsWorkDefinitionAdminImpl(workDefCache, workDefService, attributeResolverService,
          teamWorkflowProvidersLazy);
 
diff --git a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/AtsConfigEndpointImpl.java b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/AtsConfigEndpointImpl.java
index 9e4fa29..d6624f3 100644
--- a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/AtsConfigEndpointImpl.java
+++ b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/AtsConfigEndpointImpl.java
@@ -83,6 +83,7 @@
             ResultSet<ArtifactReadable> artifacts =
                orcsApi.getQueryFactory().fromBranch(CoreBranches.COMMON).andTypeEquals(
                   AtsArtifactTypes.Configuration).getResults();
+            // load ats branch configurations
             AtsConfigurations configs = new AtsConfigurations();
             for (ArtifactReadable art : artifacts) {
                AtsConfiguration config = new AtsConfiguration();
@@ -95,26 +96,36 @@
             }
             UpdateAtsConfiguration update = new UpdateAtsConfiguration(atsServer);
             AtsViews views = update.getConfigViews();
+            // load views
             configs.setViews(views);
+            // load color column config
             configs.setColorColumns(update.getColorColumns());
+            // load valid state names
+            configs.setValidStateNames(update.getValidStateNames());
+            // load users
             for (IAtsUser user : atsServer.getUserService().getUsers()) {
                configs.getUsers().add((JaxAtsUser) user);
             }
+            // load admins
             ArtifactReadable atsAdminArt = orcsApi.getQueryFactory().fromBranch(AtsUtilCore.getAtsBranch()).andIds(
                AtsArtifactToken.AtsAdmin).getResults().getAtMostOneOrNull();
             if (atsAdminArt != null) {
-               for (ArtifactReadable member : atsAdminArt.getRelated(CoreRelationTypes.User_Grouping__Members)) {
-                  IAtsUser found = configs.getUsers().stream().filter(
-                     user -> user.getUuid().equals(member.getUuid())).findFirst().orElse(null);
-                  if (found != null) {
-                     configs.getAtsAdmins().add((JaxAtsUser) found);
-                  }
+               for (ArtifactReadable member : atsAdminArt.getRelated(CoreRelationTypes.Users_User)) {
+                  configs.getAtsAdmins().add(member.getId());
                }
             }
+            // load ats config object ids
             for (HasLocalId<Integer> configArtId : orcsApi.getQueryFactory().fromBranch(
                AtsUtilCore.getAtsBranch()).andIsOfType(AtsArtifactTypes.TeamDefinition, AtsArtifactTypes.Version,
                   AtsArtifactTypes.ActionableItem).getResultsAsLocalIds()) {
-               configs.getAtsActiveConfigIds().add(configArtId.getLocalId());
+               configs.getAtsConfigIds().add(Long.valueOf(configArtId.getLocalId()));
+            }
+            // load work definitions
+            for (ArtifactId workDefArt : orcsApi.getQueryFactory().fromBranch(AtsUtilCore.getAtsBranch()).andIsOfType(
+               AtsArtifactTypes.WorkDefinition).getResults()) {
+               String workDefStr = atsServer.getAttributeResolver().getSoleAttributeValueAsString(workDefArt,
+                  AtsAttributeTypes.DslSheet, "");
+               configs.getWorkDefIdToWorkDef().put(workDefArt.getName(), workDefStr);
             }
             return configs;
          }
@@ -192,7 +203,6 @@
       ArtifactId workDefFolder =
          introduceAndRelateTo(tx, fromBranch, AtsArtifactToken.WorkDefinitionsFolder, newBranch, null, headingArt);
       introduceAndRelateTo(tx, fromBranch, AtsArtifactToken.Users, newBranch, null, configArt);
-      introduceAndRelateTo(tx, fromBranch, AtsArtifactToken.WorkDef_State_Names, newBranch, null, workDefFolder);
 
       // Introduce default work defs
       introduceAndRelateTo(tx, fromBranch, AtsArtifactToken.WorkDef_Goal, newBranch, null, workDefFolder);
diff --git a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/ConvertCreateUpdateAtsConfig.java b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/ConvertCreateUpdateAtsConfig.java
index bbe4c5a..331cf8e 100644
--- a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/ConvertCreateUpdateAtsConfig.java
+++ b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/ConvertCreateUpdateAtsConfig.java
@@ -16,7 +16,7 @@
 
 /**
  * See description below
- * 
+ *
  * @author Donald G Dunne
  */
 public class ConvertCreateUpdateAtsConfig implements IAtsDatabaseConversion {
@@ -42,8 +42,13 @@
    public String getDescription() {
       StringBuffer data = new StringBuffer();
       data.append("Updates AtsConfig artifact (optional but recommended conversion)\n\n");
-      data.append(
-         "This will add any new ATS columns that have been configured.\n\nCan be run multiple times without corruption.\nShould be run after each release.");
+      data.append("This will:\n" + "   - Create AtsConfig artifact, if not created\n" //
+         + "   - Create Rule Definitions from support/ruleDefinitions.ats, if not created\n" //
+         + "   - Create/Update Views from support/views.json\n" //
+         + "   - Create Color Team Column, if not created.\n" //
+         + "   - Create/Update Valid State Names\n\n" //
+         + "Can be run multiple times without corruption.\n" //
+         + "Should be run after each release.");
       return data.toString();
    }
 
diff --git a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/UpdateAtsConfiguration.java b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/UpdateAtsConfiguration.java
index 616cbae..bfcc22c 100644
--- a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/UpdateAtsConfiguration.java
+++ b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/config/UpdateAtsConfiguration.java
@@ -12,9 +12,11 @@
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.logging.Level;
 import org.eclipse.osee.ats.api.config.AtsAttributeValueColumn;
 import org.eclipse.osee.ats.api.config.AtsViews;
 import org.eclipse.osee.ats.api.data.AtsArtifactToken;
@@ -29,11 +31,12 @@
 import org.eclipse.osee.framework.core.enums.CoreBranches;
 import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
 import org.eclipse.osee.framework.core.enums.DeletionFlag;
-import org.eclipse.osee.framework.core.exception.OseeWrappedException;
 import org.eclipse.osee.framework.core.util.XResultData;
 import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
 import org.eclipse.osee.framework.jdk.core.type.OseeStateException;
+import org.eclipse.osee.framework.jdk.core.util.Collections;
 import org.eclipse.osee.framework.jdk.core.util.Strings;
+import org.eclipse.osee.framework.logging.OseeLog;
 import org.eclipse.osee.orcs.data.ArtifactReadable;
 import org.eclipse.osee.orcs.data.AttributeReadable;
 import org.eclipse.osee.orcs.transaction.TransactionBuilder;
@@ -48,7 +51,7 @@
    private static final String VIEWS_KEY = "views";
    private static final String VIEWS_EQUAL_KEY = VIEWS_KEY + "=";
    private static final String COLOR_COLUMN_KEY = "colorColumns";
-   private static final String COLOR_COLUMN_EQUAL_KEY = COLOR_COLUMN_KEY + "=";
+   public static final String VALID_STATE_NAMES_KEY = "validStateNames";
 
    public UpdateAtsConfiguration(IAtsServer atsServer) {
       this.atsServer = atsServer;
@@ -58,36 +61,43 @@
    public XResultData createUpdateConfig(XResultData rd) {
       ArtifactReadable userArt = atsServer.getArtifact(AtsCoreUsers.SYSTEM_USER);
       ArtifactId configFolder = getOrCreateConfigFolder(userArt, rd);
-      getOrCreateAtsConfig(userArt, rd);
-      importRuleDefinitions(userArt, configFolder, rd);
+      ArtifactReadable atsConfigArt = (ArtifactReadable) getOrCreateAtsConfig(userArt, rd);
+      createRuleDefinitions(userArt, configFolder, rd);
+      createUpdateColorColumnAttributes(atsConfigArt, userArt, rd);
+      createUpdateConfigAttributes(atsConfigArt, userArt, rd);
+      createUpdateValidStateAttributes(atsConfigArt, userArt, rd);
       return rd;
    }
 
-   private void importRuleDefinitions(ArtifactReadable userArt, ArtifactId configFolderArt, XResultData rd) {
+   private void createRuleDefinitions(ArtifactReadable userArt, ArtifactId configFolderArt, XResultData rd) {
       try {
-         TransactionBuilder tx = atsServer.getOrcsApi().getTransactionFactory().createTransaction(CoreBranches.COMMON,
-            userArt, "Add Rule Definitions");
-         ArtifactId ruleDefConfigArt = tx.createArtifact(AtsArtifactToken.RuleDefinitions);
-         String ruleDefs = RestUtil.getResource("support/ruleDefinitions.ats");
-         tx.createAttribute(ruleDefConfigArt, AtsAttributeTypes.DslSheet, ruleDefs);
-         if (rd.isErrors()) {
-            throw new OseeStateException(rd.toString());
+         if (atsServer.getArtifact(AtsArtifactToken.RuleDefinitions) == null) {
+            TransactionBuilder tx = atsServer.getOrcsApi().getTransactionFactory().createTransaction(
+               CoreBranches.COMMON, userArt, "Add Rule Definitions Artifact");
+            ArtifactId ruleDefConfigArt = tx.createArtifact(AtsArtifactToken.RuleDefinitions);
+            String ruleDefs = RestUtil.getResource("support/ruleDefinitions.ats");
+            tx.createAttribute(ruleDefConfigArt, AtsAttributeTypes.DslSheet, ruleDefs);
+            if (rd.isErrors()) {
+               throw new OseeStateException(rd.toString());
+            }
+            tx.relate(configFolderArt, CoreRelationTypes.Default_Hierarchical__Child, ruleDefConfigArt);
+            tx.commit();
          }
-         tx.relate(configFolderArt, CoreRelationTypes.Default_Hierarchical__Child, ruleDefConfigArt);
-         tx.commit();
       } catch (Exception ex) {
-         throw new OseeWrappedException("Error loading column ruleDefinitions.ats file", ex);
+         OseeLog.log(UpdateAtsConfiguration.class, Level.SEVERE, ex);
+         rd.error("Error loading column ruleDefinitions.ats file (see log for details) " + ex.getLocalizedMessage());
       }
    }
 
-   private TransactionBuilder setConfigAttributes(ArtifactReadable configArt, ArtifactReadable userArt, TransactionBuilder tx, XResultData rd) throws OseeCoreException {
+   private void createUpdateConfigAttributes(ArtifactReadable configArt, ArtifactReadable userArt, XResultData rd) throws OseeCoreException {
       try {
          String viewsJson = RestUtil.getResource("support/views.json");
          AtsViews defaultViews = gson.fromJson(viewsJson, AtsViews.class);
          AtsViews databaseViews = getConfigViews();
+         TransactionBuilder tx = atsServer.getOrcsApi().getTransactionFactory().createTransaction(CoreBranches.COMMON,
+            userArt, "Create Update Config Attributes");
          if (databaseViews.getAttrColumns().isEmpty()) {
-            tx = getOrCreateTx(userArt, tx);
-            tx.createAttribute(configArt, CoreAttributeTypes.GeneralStringData, createViewsAttrValue(defaultViews));
+            tx.createAttribute(configArt, CoreAttributeTypes.GeneralStringData, getViewsAttrValue(defaultViews));
             rd.log("Creating VIEWS attribute\n");
          } else {
             // merge any new default view items to current database view items
@@ -116,28 +126,20 @@
             while (iterator.hasNext()) {
                AttributeReadable<Object> attributeReadable = iterator.next();
                if (((String) attributeReadable.getValue()).startsWith(VIEWS_EQUAL_KEY)) {
-                  tx = getOrCreateTx(userArt, tx);
-                  tx.setAttributeById(configArt, attributeReadable, createViewsAttrValue(databaseViews));
+                  tx.setAttributeById(configArt, attributeReadable, getViewsAttrValue(databaseViews));
                   rd.log("Create or update AtsConfig.VIEWS attribute\n");
                   break;
                }
             }
          }
+         tx.commit();
       } catch (Exception ex) {
-         throw new OseeWrappedException("Error loading column views.json file", ex);
+         OseeLog.log(UpdateAtsConfiguration.class, Level.SEVERE, ex);
+         rd.error("Error loading column views.json file (see log for details) " + ex.getLocalizedMessage());
       }
-      return tx;
    }
 
-   private TransactionBuilder getOrCreateTx(ArtifactReadable userArt, TransactionBuilder tx) {
-      if (tx == null) {
-         tx = atsServer.getOrcsApi().getTransactionFactory().createTransaction(CoreBranches.COMMON, userArt,
-            "Update AtsConfig attributes");
-      }
-      return tx;
-   }
-
-   private String createViewsAttrValue(AtsViews defaultViews) {
+   private String getViewsAttrValue(AtsViews defaultViews) {
       return VIEWS_EQUAL_KEY + gson.toJson(defaultViews);
    }
 
@@ -157,7 +159,6 @@
          tx.commit();
          rd.log("Created Config Folder");
       }
-
       return configFolderArt;
    }
 
@@ -171,44 +172,22 @@
          ArtifactReadable headingFolderArt = (ArtifactReadable) getOrCreateConfigFolder(userArt, rd);
          atsConfigArt = (ArtifactReadable) tx.createArtifact(AtsArtifactToken.AtsConfig);
          tx.relate(headingFolderArt, CoreRelationTypes.Default_Hierarchical__Parent, atsConfigArt);
-         setConfigAttributes(atsConfigArt, userArt, tx, rd);
-         setColorColumnAttributes(atsConfigArt, userArt, tx, rd);
          tx.commit();
          rd.log("Created AtsConfig");
-      } else {
-         TransactionBuilder tx = setConfigAttributes(atsConfigArt, userArt, null, rd);
-         if (tx != null) {
-            tx.commit();
-         }
       }
-
       return atsConfigArt;
    }
 
-   private void setColorColumnAttributes(ArtifactReadable atsConfigArt, ArtifactReadable userArt, TransactionBuilder tx, XResultData rd) {
+   private void createUpdateColorColumnAttributes(ArtifactReadable atsConfigArt, ArtifactReadable userArt, XResultData rd) {
       ColorColumns columns = new ColorColumns();
       columns.addColumn(ColorTeamColumn.getColor());
       String colorColumnsJson = gson.toJson(columns);
+      atsServer.setConfigValue(COLOR_COLUMN_KEY, colorColumnsJson);
+   }
 
-      Iterator<? extends AttributeReadable<Object>> iterator =
-         atsConfigArt.getAttributes(CoreAttributeTypes.GeneralStringData, DeletionFlag.EXCLUDE_DELETED).iterator();
-      boolean found = false;
-      while (iterator.hasNext()) {
-         AttributeReadable<Object> attributeReadable = iterator.next();
-         if (((String) attributeReadable.getValue()).startsWith(COLOR_COLUMN_EQUAL_KEY)) {
-            tx = getOrCreateTx(userArt, tx);
-            tx.setAttributeById(atsConfigArt, attributeReadable, colorColumnsJson);
-            found = true;
-            rd.log("Create or update AtsConfig.colorColumn attribute\n");
-            break;
-         }
-      }
-      if (!found) {
-         tx = getOrCreateTx(userArt, tx);
-         tx.createAttribute(atsConfigArt, CoreAttributeTypes.GeneralStringData,
-            COLOR_COLUMN_EQUAL_KEY + colorColumnsJson);
-      }
-
+   private void createUpdateValidStateAttributes(ArtifactReadable atsConfigArt, ArtifactReadable userArt, XResultData rd) {
+      Collection<String> validStateNames = atsServer.getWorkDefService().getAllValidStateNames(new XResultData());
+      atsServer.setConfigValue(VIEWS_KEY, Collections.toString(",", validStateNames));
    }
 
    @SuppressWarnings("unchecked")
@@ -227,6 +206,17 @@
       return configsFolderArt;
    }
 
+   public Collection<String> getValidStateNames() {
+      String stateNamesStr = atsServer.getConfigValue(VALID_STATE_NAMES_KEY);
+      List<String> stateNames = new LinkedList<>();
+      if (Strings.isValid(stateNamesStr)) {
+         for (String stateName : stateNamesStr.split(",")) {
+            stateNames.add(stateName);
+         }
+      }
+      return stateNames;
+   }
+
    public AtsViews getConfigViews() {
       String viewsStr = atsServer.getConfigValue(VIEWS_KEY);
       AtsViews views = null;
diff --git a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/convert/AbstractConvertGuidToUuid.java b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/convert/AbstractConvertGuidToUuid.java
index 1f489fe..095fd49 100644
--- a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/convert/AbstractConvertGuidToUuid.java
+++ b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/convert/AbstractConvertGuidToUuid.java
@@ -30,10 +30,10 @@
 
    private static final String SELECT_BRANCH_ID_BY_GUID = "select branch_id from osee_branch where branch_guid = ?";
 
-   private final Log logger;
-   private final JdbcClient jdbcClient;
-   private final OrcsApi orcsApi;
-   private final IAtsServer atsServer;
+   protected final Log logger;
+   protected final JdbcClient jdbcClient;
+   protected final OrcsApi orcsApi;
+   protected final IAtsServer atsServer;
 
    public AbstractConvertGuidToUuid(Log logger, JdbcClient jdbcClient, OrcsApi orcsApi, IAtsServer atsServer) {
       super();
diff --git a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/util/AtsAttributeResolverServiceImpl.java b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/util/AtsAttributeResolverServiceImpl.java
index 0c489ad..93b417e 100644
--- a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/util/AtsAttributeResolverServiceImpl.java
+++ b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/util/AtsAttributeResolverServiceImpl.java
@@ -14,6 +14,7 @@
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.osee.ats.api.IAtsObject;
 import org.eclipse.osee.ats.api.IAtsWorkItem;
 import org.eclipse.osee.ats.api.util.IAtsChangeSet;
@@ -236,9 +237,16 @@
       return getAttributeValues(atsObject.getStoreObject(), attributeType);
    }
 
+   @SuppressWarnings("unchecked")
    @Override
    public <T> Collection<IAttribute<T>> getAttributes(ArtifactId artifact, IAttributeType attributeType) throws OseeCoreException {
-      return getArtifact(artifact).getAttributeValues(attributeType);
+      Assert.isNotNull(artifact, "Artifact can not be null");
+      Assert.isNotNull(attributeType, "Attribute Type can not be null");
+      List<IAttribute<T>> attributes = new LinkedList<>();
+      for (AttributeReadable<Object> attr : ((ArtifactReadable) artifact).getAttributes(attributeType)) {
+         attributes.add(new AttributeReadableWrapper<T>((AttributeReadable<T>) attr));
+      }
+      return attributes;
    }
 
    @Override
diff --git a/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/util/AttributeReadableWrapper.java b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/util/AttributeReadableWrapper.java
new file mode 100644
index 0000000..644bebb
--- /dev/null
+++ b/plugins/org.eclipse.osee.ats.rest/src/org/eclipse/osee/ats/rest/internal/util/AttributeReadableWrapper.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.ats.rest.internal.util;
+
+import org.eclipse.osee.ats.api.workflow.IAttribute;
+import org.eclipse.osee.framework.core.data.IAttributeType;
+import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
+import org.eclipse.osee.orcs.data.AttributeReadable;
+
+/**
+ * @author Donald G. Dunne
+ */
+public class AttributeReadableWrapper<T> implements IAttribute<T> {
+
+   private final AttributeReadable<T> attr;
+
+   public AttributeReadableWrapper(AttributeReadable<T> attr) {
+      this.attr = attr;
+   }
+
+   @Override
+   public T getValue() throws OseeCoreException {
+      return attr.getValue();
+   }
+
+   @Override
+   public Object getData() {
+      return attr;
+   }
+
+   @Override
+   public void delete() throws OseeCoreException {
+      throw new UnsupportedOperationException("delete not supported on server");
+   }
+
+   @Override
+   public void setValue(T value) throws OseeCoreException {
+      throw new UnsupportedOperationException("setValue not supported on server");
+   }
+
+   @Override
+   public int getId() {
+      return attr.getId().intValue();
+   }
+
+   @Override
+   public IAttributeType getAttrType() {
+      return attr.getAttributeType();
+   }
+
+}
diff --git a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/search/widget/StateNameSearchWidget.java b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/search/widget/StateNameSearchWidget.java
index f9ea962..4da7e96 100644
--- a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/search/widget/StateNameSearchWidget.java
+++ b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/search/widget/StateNameSearchWidget.java
@@ -13,7 +13,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import org.eclipse.osee.ats.api.query.AtsSearchData;
-import org.eclipse.osee.ats.workdef.AtsWorkDefinitionSheetProviders;
+import org.eclipse.osee.ats.internal.AtsClientService;
 import org.eclipse.osee.ats.world.WorldEditorParameterSearchItem;
 import org.eclipse.osee.framework.jdk.core.util.Strings;
 
@@ -41,6 +41,6 @@
 
    @Override
    public Collection<String> getInput() {
-      return AtsWorkDefinitionSheetProviders.getAllValidStateNames();
+      return AtsClientService.get().getConfigurations().getValidStateNames();
    }
 }
diff --git a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/util/widgets/XStateSearchCombo.java b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/util/widgets/XStateSearchCombo.java
index 09f068a..1793aef 100644
--- a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/util/widgets/XStateSearchCombo.java
+++ b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/util/widgets/XStateSearchCombo.java
@@ -13,7 +13,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import org.eclipse.osee.ats.workdef.AtsWorkDefinitionSheetProviders;
+import org.eclipse.osee.ats.internal.AtsClientService;
 import org.eclipse.osee.framework.ui.skynet.widgets.XComboViewer;
 import org.eclipse.osee.framework.ui.skynet.widgets.XModifiedListener;
 import org.eclipse.osee.framework.ui.skynet.widgets.XWidget;
@@ -39,7 +39,7 @@
    protected synchronized void ensurePopulated() {
       if (validStates.isEmpty()) {
          validStates.add("--select--");
-         validStates.addAll(AtsWorkDefinitionSheetProviders.getAllValidStateNames());
+         validStates.addAll(AtsClientService.get().getConfigurations().getValidStateNames());
          Collections.sort(validStates);
       }
    }
diff --git a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/workdef/AtsWorkDefinitionSheetProviders.java b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/workdef/AtsWorkDefinitionSheetProviders.java
index 7f89de6..f7a0d0c 100644
--- a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/workdef/AtsWorkDefinitionSheetProviders.java
+++ b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/workdef/AtsWorkDefinitionSheetProviders.java
@@ -14,7 +14,6 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -30,11 +29,8 @@
 import org.eclipse.osee.ats.core.workdef.WorkDefinitionSheet;
 import org.eclipse.osee.ats.dsl.atsDsl.AtsDsl;
 import org.eclipse.osee.ats.internal.Activator;
-import org.eclipse.osee.ats.internal.AtsClientService;
 import org.eclipse.osee.ats.workdef.config.ImportAIsAndTeamDefinitionsToDb;
 import org.eclipse.osee.ats.workdef.provider.AtsWorkDefinitionImporter;
-import org.eclipse.osee.framework.core.enums.CoreAttributeTypes;
-import org.eclipse.osee.framework.core.exception.ArtifactDoesNotExist;
 import org.eclipse.osee.framework.core.util.XResultData;
 import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
 import org.eclipse.osee.framework.logging.OseeLevel;
@@ -42,8 +38,6 @@
 import org.eclipse.osee.framework.plugin.core.PluginUtil;
 import org.eclipse.osee.framework.skynet.core.OseeSystemArtifacts;
 import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
-import org.eclipse.osee.framework.skynet.core.artifact.ArtifactTypeManager;
-import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery;
 import org.osgi.framework.Bundle;
 
 /**
@@ -53,7 +47,6 @@
 
    private static Set<IAtsWorkDefinitionSheetProvider> teamWorkflowExtensionItems;
    public static String WORK_DEF_TEAM_DEFAULT = "WorkDef_Team_Default";
-   private static List<String> allValidStateNames = null;
 
    private AtsWorkDefinitionSheetProviders() {
       // Utility Class
@@ -69,57 +62,10 @@
       List<WorkDefinitionSheet> sheets = getWorkDefinitionSheets();
       Set<String> stateNames = new HashSet<>();
       importWorkDefinitionSheets(resultData, changes, folder, sheets, stateNames);
-      createStateNameArtifact(stateNames, folder, changes);
       importTeamsAndAis(resultData, changes, folder, sheets);
       changes.execute();
    }
 
-   /**
-    * Returns all valid state names for all work definitions in the system
-    */
-   public synchronized static Collection<String> getAllValidStateNames() {
-      if (allValidStateNames == null) {
-         allValidStateNames = new ArrayList<>();
-         try {
-            Artifact artifact = null;
-            try {
-               artifact = ArtifactQuery.getArtifactFromToken(
-                  org.eclipse.osee.ats.api.data.AtsArtifactToken.WorkDef_State_Names, AtsUtilCore.getAtsBranch());
-            } catch (ArtifactDoesNotExist ex) {
-               // do nothing
-            }
-            if (artifact != null) {
-               for (String value : artifact.getSoleAttributeValue(CoreAttributeTypes.GeneralStringData, "").split(
-                  ",")) {
-                  allValidStateNames.add(value);
-               }
-            } else {
-               XResultData resultData = new XResultData(false);
-               OseeLog.logf(AtsWorkDefinitionSheetProviders.class, Level.INFO,
-                  "ATS Valid State Names: Missing [%s] Artifact; Falling back to loadAddDefinitions",
-                  org.eclipse.osee.ats.api.data.AtsArtifactToken.WorkDef_State_Names.getName());
-               allValidStateNames.addAll(
-                  AtsClientService.get().getWorkDefinitionAdmin().getAllValidStateNames(resultData));
-            }
-            Collections.sort(allValidStateNames);
-         } catch (Exception ex) {
-            OseeLog.log(AtsWorkDefinitionSheetProviders.class, Level.SEVERE, ex);
-         }
-      }
-      return allValidStateNames;
-   }
-
-   private static Artifact createStateNameArtifact(Set<String> stateNames, Artifact folder, IAtsChangeSet changes) throws OseeCoreException {
-      Artifact stateNameArt = ArtifactTypeManager.addArtifact(
-         org.eclipse.osee.ats.api.data.AtsArtifactToken.WorkDef_State_Names, AtsUtilCore.getAtsBranch());
-      stateNameArt.addAttribute(CoreAttributeTypes.GeneralStringData,
-         org.eclipse.osee.framework.jdk.core.util.Collections.toString(",", stateNames));
-      changes.add(stateNameArt);
-      folder.addChild(stateNameArt);
-      changes.add(folder);
-      return stateNameArt;
-   }
-
    public static void importWorkDefinitionSheets(XResultData resultData, IAtsChangeSet changes, Artifact folder, Collection<WorkDefinitionSheet> sheets, Set<String> stateNames) throws OseeCoreException {
       for (WorkDefinitionSheet sheet : sheets) {
          OseeLog.logf(Activator.class, Level.INFO, "Importing ATS Work Definitions [%s]", sheet.getName());
diff --git a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/world/WorldXViewerUtil.java b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/world/WorldXViewerUtil.java
index e7f78ca..5c2d6e5 100644
--- a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/world/WorldXViewerUtil.java
+++ b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/world/WorldXViewerUtil.java
@@ -23,7 +23,6 @@
 import org.eclipse.osee.ats.internal.AtsClientService;
 import org.eclipse.osee.ats.util.AtsUtil;
 import org.eclipse.osee.ats.util.xviewer.column.XViewerAtsAttributeValueColumn;
-import org.eclipse.osee.ats.workdef.AtsWorkDefinitionSheetProviders;
 import org.eclipse.osee.framework.core.model.type.AttributeType;
 import org.eclipse.osee.framework.logging.OseeLog;
 import org.eclipse.osee.framework.skynet.core.attribute.AttributeTypeManager;
@@ -98,10 +97,8 @@
    }
 
    public static void registerStateColumns(XViewerFactory factory) {
-      for (String stateName : AtsWorkDefinitionSheetProviders.getAllValidStateNames()) {
+      for (String stateName : AtsClientService.get().getConfigurations().getValidStateNames()) {
          factory.registerColumns(new StateAssigneesColumn(stateName));
-      }
-      for (String stateName : AtsWorkDefinitionSheetProviders.getAllValidStateNames()) {
          factory.registerColumns(new StateCompletedColumn(stateName));
       }
    }