Merge "Remove.java-Replace the type specification in this constructor call with the...
[aaf/authz.git] / auth / auth-service / src / main / java / org / onap / aaf / auth / service / AuthzCassServiceImpl.java
index c3e92df..6741030 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed 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.
@@ -33,7 +33,6 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.HashMap;
@@ -43,11 +42,15 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 
 import javax.servlet.http.HttpServletRequest;
 
 import org.onap.aaf.auth.common.Define;
 import org.onap.aaf.auth.dao.DAOException;
+import org.onap.aaf.auth.dao.cached.CachedPermDAO;
+import org.onap.aaf.auth.dao.cached.CachedRoleDAO;
+import org.onap.aaf.auth.dao.cached.CachedUserRoleDAO;
 import org.onap.aaf.auth.dao.cass.ApprovalDAO;
 import org.onap.aaf.auth.dao.cass.CertDAO;
 import org.onap.aaf.auth.dao.cass.CredDAO;
@@ -68,9 +71,11 @@ import org.onap.aaf.auth.dao.hl.Function;
 import org.onap.aaf.auth.dao.hl.Function.FUTURE_OP;
 import org.onap.aaf.auth.dao.hl.Function.Lookup;
 import org.onap.aaf.auth.dao.hl.Function.OP_STATUS;
+import org.onap.aaf.auth.dao.hl.PermLookup;
 import org.onap.aaf.auth.dao.hl.Question;
 import org.onap.aaf.auth.dao.hl.Question.Access;
 import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.env.AuthzTrans.REQD_TYPE;
 import org.onap.aaf.auth.layer.Result;
 import org.onap.aaf.auth.org.Executor;
 import org.onap.aaf.auth.org.Organization;
@@ -83,7 +88,9 @@ import org.onap.aaf.auth.service.mapper.Mapper;
 import org.onap.aaf.auth.service.mapper.Mapper.API;
 import org.onap.aaf.auth.service.validation.ServiceValidator;
 import org.onap.aaf.auth.validation.Validator;
+import org.onap.aaf.cadi.aaf.Defaults;
 import org.onap.aaf.cadi.principal.BasicPrincipal;
+import org.onap.aaf.cadi.util.FQI;
 import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.TimeTaken;
 import org.onap.aaf.misc.env.util.Chrono;
@@ -92,8 +99,8 @@ import org.onap.aaf.misc.env.util.Split;
 import aaf.v2_0.CredRequest;
 
 /**
- * AuthzCassServiceImpl implements AuthzCassService for 
- * 
+ * AuthzCassServiceImpl implements AuthzCassService for
+ *
  * @author Jonathan
  *
  * @param <NSS>
@@ -109,11 +116,12 @@ import aaf.v2_0.CredRequest;
  */
 public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS>
     implements AuthzService            <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> {
-    
+
+    private static final String TWO_SPACE = "  ";
     private Mapper                    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> mapper;
     @Override
     public Mapper                    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> mapper() {return mapper;}
-    
+
     private static final String ASTERIX = "*";
     private static final String CACHE = "cache";
     private static final String ROOT_NS = Define.ROOT_NS();
@@ -121,28 +129,28 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
 
     private final Question ques;
     private final Function func;
-    
+
     public AuthzCassServiceImpl(AuthzTrans trans, Mapper<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> mapper,Question question) {
         this.ques = question;
         func = new Function(trans, question);
         this.mapper = mapper;
-        
+
     }
 
 /***********************************
- * NAMESPACE 
+ * NAMESPACE
  ***********************************/
     /**
      * createNS
-     * @throws DAOException 
+     * @throws DAOException
      * @see org.onap.aaf.auth.service.AuthzService#createNS(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.String, java.lang.String)
      */
-    @ApiDoc( 
-            method = POST,  
+    @ApiDoc(
+            method = POST,
             path = "/authz/ns",
             params = {},
             expectedCode = 201,
-            errorCodes = { 403,404,406,409 }, 
+            errorCodes = { 403,404,406,409 },
             text = { "Namespace consists of: ",
                     "<ul><li>name - What you want to call this Namespace</li>",
                     "<li>responsible(s) - Person(s) who receive Notifications and approves Requests ",
@@ -160,20 +168,21 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> createNS(final AuthzTrans trans, REQUEST from, NsType type) {
         final Result<Namespace> rnamespace = mapper.ns(trans, from);
         final ServiceValidator v = new ServiceValidator();
-        if(v.ns(rnamespace).err()) { 
+        if (v.ns(rnamespace).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         final Namespace namespace = rnamespace.value;
         final Result<NsDAO.Data> parentNs = ques.deriveNs(trans,namespace.name);
-        if(parentNs.notOK()) {
+        if (parentNs.notOK()) {
             return Result.err(parentNs);
         }
-        
-        if(namespace.name.lastIndexOf('.')<0) { // Root Namespace... Function will check if allowed
+
+        // Note: Data validate occurs in func.createNS
+        if (namespace.name.lastIndexOf('.')<0) { // Root Namespace... Function will check if allowed
             return func.createNS(trans, namespace, false);
         }
-        
-        Result<FutureDAO.Data> fd = mapper.future(trans, NsDAO.TABLE,from,namespace,true, 
+
+        Result<FutureDAO.Data> fd = mapper.future(trans, NsDAO.TABLE,from,namespace,true,
                 new Mapper.Memo() {
                     @Override
                     public String get() {
@@ -184,7 +193,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     private Result<NsDAO.Data> rnd;
                     @Override
                     public Result<?> mayChange() {
-                        if(rnd==null) {
+                        if (rnd==null) {
                             rnd = ques.mayUser(trans, trans.user(), parentNs.value,Access.write);
                         }
                         return rnd;
@@ -193,9 +202,9 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             switch(fd.status) {
                 case OK:
                     Result<String> rfc = func.createFuture(trans, fd.value, namespace.name, trans.user(),parentNs.value, FUTURE_OP.C);
-                    if(rfc.isOK()) {
+                    if (rfc.isOK()) {
                         return Result.err(Status.ACC_Future, "NS [%s] is saved for future processing",namespace.name);
-                    } else { 
+                    } else {
                         return Result.err(rfc);
                     }
                 case Status.ACC_Now:
@@ -204,16 +213,16 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     return Result.err(fd);
             }
     }
-    
+
     @ApiDoc(
-            method = POST,  
+            method = POST,
             path = "/authz/ns/:ns/admin/:id",
             params = {     "ns|string|true",
-                        "id|string|true" 
+                        "id|string|true"
                     },
             expectedCode = 201,
-            errorCodes = { 403,404,406,409 }, 
-            text = {     "Add an Identity :id to the list of Admins for the Namespace :ns", 
+            errorCodes = { 403,404,406,409 },
+            text = {     "Add an Identity :id to the list of Admins for the Namespace :ns",
                         "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)" }
             )
     @Override
@@ -222,13 +231,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     @ApiDoc(
-            method = DELETE,  
+            method = DELETE,
             path = "/authz/ns/:ns/admin/:id",
             params = {     "ns|string|true",
-                        "id|string|true" 
+                        "id|string|true"
                     },
             expectedCode = 200,
-            errorCodes = { 403,404 }, 
+            errorCodes = { 403,404 },
             text = {     "Remove an Identity :id from the list of Admins for the Namespace :ns",
                         "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)" }
             )
@@ -238,13 +247,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     @ApiDoc(
-            method = POST,  
+            method = POST,
             path = "/authz/ns/:ns/responsible/:id",
             params = {     "ns|string|true",
-                        "id|string|true" 
+                        "id|string|true"
                     },
             expectedCode = 201,
-            errorCodes = { 403,404,406,409 }, 
+            errorCodes = { 403,404,406,409 },
             text = {     "Add an Identity :id to the list of Responsibles for the Namespace :ns",
                         "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)" }
             )
@@ -254,13 +263,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     @ApiDoc(
-            method = DELETE,  
+            method = DELETE,
             path = "/authz/ns/:ns/responsible/:id",
             params = {     "ns|string|true",
-                        "id|string|true" 
+                        "id|string|true"
                     },
             expectedCode = 200,
-            errorCodes = { 403,404 }, 
+            errorCodes = { 403,404 },
             text = {     "Remove an Identity :id to the list of Responsibles for the Namespace :ns",
                         "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)",
                         "Note: A namespace must have at least 1 responsible party"
@@ -275,14 +284,14 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
      * @see org.onap.aaf.auth.service.AuthzService#applyModel(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
      */
     @ApiDoc(
-            method = POST,  
+            method = POST,
             path = "/authz/ns/:ns/attrib/:key/:value",
             params = {     "ns|string|true",
                         "key|string|true",
                         "value|string|true"},
             expectedCode = 201,
-            errorCodes = { 403,404,406,409 },  
-            text = {     
+            errorCodes = { 403,404,406,409 },
+            text = {
                 "Create an attribute in the Namespace",
                 "You must be given direct permission for key by AAF"
                 }
@@ -293,46 +302,47 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         try {
             // Check inputs
             final Validator v = new ServiceValidator();
-            if(v.ns(ns).err() ||
+            if (v.ns(ns).err() ||
                v.key(key).err() ||
                v.value(value).err()) {
                 return Result.err(Status.ERR_BadData,v.errs());
             }
 
             // Check if exists already
-            Result<List<Data>> rlnsd = ques.nsDAO.read(trans, ns);
-            if(rlnsd.notOKorIsEmpty()) {
+            Result<List<Data>> rlnsd = ques.nsDAO().read(trans, ns);
+            if (rlnsd.notOKorIsEmpty()) {
                 return Result.err(rlnsd);
             }
             NsDAO.Data nsd = rlnsd.value.get(0);
 
             // Check for Existence
-            if(nsd.attrib.get(key)!=null) {
+            if (nsd.attrib.get(key)!=null) {
                 return Result.err(Status.ERR_ConflictAlreadyExists, "NS Property %s:%s exists", ns, key);
             }
-            
+
             // Check if User may put
-            if(!ques.isGranted(trans, trans.user(), ROOT_NS, Question.ATTRIB, 
+            if (!ques.isGranted(trans, trans.user(), ROOT_NS, Question.ATTRIB,
                     ":"+trans.org().getDomain()+".*:"+key, Access.write.name())) {
                 return Result.err(Status.ERR_Denied, "%s may not create NS Attrib [%s:%s]", trans.user(),ns, key);
             }
 
             // Add Attrib
             nsd.attrib.put(key, value);
-            ques.nsDAO.dao().attribAdd(trans,ns,key,value);
+            ques.nsDAO().dao().attribAdd(trans,ns,key,value);
+            ques.nsDAO().invalidate(trans, nsd);
             return Result.ok();
         } finally {
             tt.done();
         }
     }
-    
+
     @ApiDoc(
-            method = GET,  
+            method = GET,
             path = "/authz/ns/attrib/:key",
             params = {     "key|string|true" },
             expectedCode = 200,
-            errorCodes = { 403,404 },  
-            text = {     
+            errorCodes = { 403,404 },
+            text = {
                 "Read Attributes for Namespace"
                 }
             )
@@ -340,18 +350,18 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<KEYS> readNsByAttrib(AuthzTrans trans, String key) {
         // Check inputs
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Key",key).err()) {
+        if (v.nullOrBlank("Key",key).err()) {
               return Result.err(Status.ERR_BadData,v.errs());
         }
 
         // May Read
-        if(!ques.isGranted(trans, trans.user(), ROOT_NS, Question.ATTRIB, 
+        if (!ques.isGranted(trans, trans.user(), ROOT_NS, Question.ATTRIB,
                     ":"+trans.org().getDomain()+".*:"+key, Question.READ)) {
             return Result.err(Status.ERR_Denied,"%s may not read NS by Attrib '%s'",trans.user(),key);
         }
 
-        Result<Set<String>> rsd = ques.nsDAO.dao().readNsByAttrib(trans, key);
-        if(rsd.notOK()) {
+        Result<Set<String>> rsd = ques.nsDAO().dao().readNsByAttrib(trans, key);
+        if (rsd.notOK()) {
             return Result.err(rsd);
         }
         return mapper().keys(rsd.value);
@@ -359,13 +369,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
 
 
     @ApiDoc(
-            method = PUT,  
+            method = PUT,
             path = "/authz/ns/:ns/attrib/:key/:value",
             params = {     "ns|string|true",
                         "key|string|true"},
             expectedCode = 200,
-            errorCodes = { 403,404 },  
-            text = {     
+            errorCodes = { 403,404 },
+            text = {
                 "Update Value on an existing attribute in the Namespace",
                 "You must be given direct permission for key by AAF"
                 }
@@ -376,48 +386,48 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         try {
             // Check inputs
             final Validator v = new ServiceValidator();
-            if(v.ns(ns).err() ||
+            if (v.ns(ns).err() ||
                v.key(key).err() ||
                v.value(value).err()) {
                 return Result.err(Status.ERR_BadData,v.errs());
             }
 
             // Check if exists already (NS must exist)
-            Result<List<Data>> rlnsd = ques.nsDAO.read(trans, ns);
-            if(rlnsd.notOKorIsEmpty()) {
+            Result<List<Data>> rlnsd = ques.nsDAO().read(trans, ns);
+            if (rlnsd.notOKorIsEmpty()) {
                 return Result.err(rlnsd);
             }
             NsDAO.Data nsd = rlnsd.value.get(0);
 
             // Check for Existence
-            if(nsd.attrib.get(key)==null) {
+            if (nsd.attrib.get(key)==null) {
                 return Result.err(Status.ERR_NotFound, "NS Property %s:%s exists", ns, key);
             }
-            
+
             // Check if User may put
-            if(!ques.isGranted(trans, trans.user(), ROOT_NS, Question.ATTRIB, 
+            if (!ques.isGranted(trans, trans.user(), ROOT_NS, Question.ATTRIB,
                     ":"+trans.org().getDomain()+".*:"+key, Access.write.name())) {
                 return Result.err(Status.ERR_Denied, "%s may not create NS Attrib [%s:%s]", trans.user(),ns, key);
             }
 
             // Add Attrib
             nsd.attrib.put(key, value);
+            ques.nsDAO().invalidate(trans, nsd);
+            return ques.nsDAO().update(trans,nsd);
 
-            return ques.nsDAO.update(trans,nsd);
         } finally {
             tt.done();
         }
     }
 
     @ApiDoc(
-            method = DELETE,  
+            method = DELETE,
             path = "/authz/ns/:ns/attrib/:key",
             params = {     "ns|string|true",
                         "key|string|true"},
             expectedCode = 200,
-            errorCodes = { 403,404 },  
-            text = {     
+            errorCodes = { 403,404 },
+            text = {
                 "Delete an attribute in the Namespace",
                 "You must be given direct permission for key by AAF"
                 }
@@ -428,31 +438,32 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         try {
             // Check inputs
             final Validator v = new ServiceValidator();
-            if(v.nullOrBlank("NS",ns).err() ||
+            if (v.nullOrBlank("NS",ns).err() ||
                v.nullOrBlank("Key",key).err()) {
                 return Result.err(Status.ERR_BadData,v.errs());
             }
 
             // Check if exists already
-            Result<List<Data>> rlnsd = ques.nsDAO.read(trans, ns);
-            if(rlnsd.notOKorIsEmpty()) {
+            Result<List<Data>> rlnsd = ques.nsDAO().read(trans, ns);
+            if (rlnsd.notOKorIsEmpty()) {
                 return Result.err(rlnsd);
             }
             NsDAO.Data nsd = rlnsd.value.get(0);
 
             // Check for Existence
-            if(nsd.attrib.get(key)==null) {
+            if (nsd.attrib.get(key)==null) {
                 return Result.err(Status.ERR_NotFound, "NS Property [%s:%s] does not exist", ns, key);
             }
-            
+
             // Check if User may del
-            if(!ques.isGranted(trans, trans.user(), ROOT_NS, "attrib", ":" + ROOT_COMPANY + ".*:"+key, Access.write.name())) {
+            if (!ques.isGranted(trans, trans.user(), ROOT_NS, "attrib", ":" + ROOT_COMPANY + ".*:"+key, Access.write.name())) {
                 return Result.err(Status.ERR_Denied, "%s may not delete NS Attrib [%s:%s]", trans.user(),ns, key);
             }
 
             // Add Attrib
             nsd.attrib.remove(key);
-            ques.nsDAO.dao().attribRemove(trans,ns,key);
+            ques.nsDAO().dao().attribRemove(trans,ns,key);
+            ques.nsDAO().invalidate(trans, nsd);
             return Result.ok();
         } finally {
             tt.done();
@@ -460,44 +471,43 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     @ApiDoc(
-            method = GET,  
+            method = GET,
             path = "/authz/nss/:id",
             params = {     "id|string|true" },
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
-            text = {     
-                "Lists the Admin(s), Responsible Party(s), Role(s), Permission(s)",
-                "Credential(s) and Expiration of Credential(s) in Namespace :id",
+            errorCodes = { 404,406 },
+            text = {
+                "Lists the Owner(s), Admin(s), Description, and Attributes of Namespace :id",
             }
             )
     @Override
-    public Result<NSS> getNSbyName(AuthzTrans trans, String ns) {
+    public Result<NSS> getNSbyName(AuthzTrans trans, String ns, boolean includeExpired) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("NS", ns).err()) {
+        if (v.nullOrBlank("NS", ns).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
-        Result<List<NsDAO.Data>> rlnd = ques.nsDAO.read(trans, ns);
-        if(rlnd.isOK()) {
-            if(rlnd.isEmpty()) {
+
+        Result<List<NsDAO.Data>> rlnd = ques.nsDAO().read(trans, ns);
+        if (rlnd.isOK()) {
+            if (rlnd.isEmpty()) {
                 return Result.err(Status.ERR_NotFound, "No data found for %s",ns);
             }
             Result<NsDAO.Data> rnd = ques.mayUser(trans, trans.user(), rlnd.value.get(0), Access.read);
-            if(rnd.notOK()) {
-                return Result.err(rnd); 
+            if (rnd.notOK()) {
+                return Result.err(rnd);
             }
-            
-            
+
+
             Namespace namespace = new Namespace(rnd.value);
-            Result<List<String>> rd = func.getOwners(trans, namespace.name, false);
-            if(rd.isOK()) {
+            Result<List<String>> rd = func.getOwners(trans, namespace.name, includeExpired);
+            if (rd.isOK()) {
                 namespace.owner = rd.value;
             }
-            rd = func.getAdmins(trans, namespace.name, false);
-            if(rd.isOK()) {
+            rd = func.getAdmins(trans, namespace.name, includeExpired);
+            if (rd.isOK()) {
                 namespace.admin = rd.value;
             }
-            
+
             NSS nss = mapper.newInstance(API.NSS);
             return mapper.nss(trans, namespace, nss);
         } else {
@@ -506,13 +516,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     @ApiDoc(
-            method = GET,  
+            method = GET,
             path = "/authz/nss/admin/:id",
             params = {     "id|string|true" },
             expectedCode = 200,
-            errorCodes = { 403,404 }, 
-            text = {     "Lists all Namespaces where Identity :id is an Admin", 
-                        "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)" 
+            errorCodes = { 403,404 },
+            text = {     "Lists all Namespaces where Identity :id is an Admin",
+                        "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)"
                     }
             )
     @Override
@@ -521,13 +531,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData, v.errs());
         }
-        
+
         Result<Collection<Namespace>> rn = loadNamepace(trans, user, ".admin", full);
-        if(rn.notOK()) {
+        if (rn.notOK()) {
             return Result.err(rn);
         }
         if (rn.isEmpty()) {
-            return Result.err(Status.ERR_NotFound, "[%s] is not an admin for any namespaces",user);        
+            return Result.err(Status.ERR_NotFound, "[%s] is not an admin for any namespaces",user);
         }
         NSS nss = mapper.newInstance(API.NSS);
         // Note: "loadNamespace" already validates view of Namespace
@@ -535,13 +545,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     @ApiDoc(
-            method = GET,  
+            method = GET,
             path = "/authz/nss/either/:id",
             params = {     "id|string|true" },
             expectedCode = 200,
-            errorCodes = { 403,404 }, 
-            text = {     "Lists all Namespaces where Identity :id is either an Admin or an Owner", 
-                        "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)" 
+            errorCodes = { 403,404 },
+            text = {     "Lists all Namespaces where Identity :id is either an Admin or an Owner",
+                        "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)"
                     }
             )
     @Override
@@ -550,13 +560,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData, v.errs());
         }
-        
+
         Result<Collection<Namespace>> rn = loadNamepace(trans, user, null, full);
-        if(rn.notOK()) {
+        if (rn.notOK()) {
             return Result.err(rn);
         }
         if (rn.isEmpty()) {
-            return Result.err(Status.ERR_NotFound, "[%s] is not an admin or owner for any namespaces",user);        
+            return Result.err(Status.ERR_NotFound, "[%s] is not an admin or owner for any namespaces",user);
         }
         NSS nss = mapper.newInstance(API.NSS);
         // Note: "loadNamespace" already validates view of Namespace
@@ -564,56 +574,56 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     private Result<Collection<Namespace>> loadNamepace(AuthzTrans trans, String user, String endsWith, boolean full) {
-        Result<List<UserRoleDAO.Data>> urd = ques.userRoleDAO.readByUser(trans, user);
-        if(urd.notOKorIsEmpty()) {
+        Result<List<UserRoleDAO.Data>> urd = ques.userRoleDAO().readByUser(trans, user);
+        if (urd.notOKorIsEmpty()) {
             return Result.err(urd);
         }
         Map<String, Namespace> lm = new HashMap<>();
         Map<String, Namespace> other = full || endsWith==null?null:new TreeMap<>();
-        for(UserRoleDAO.Data urdd : urd.value) {
-            if(full) {
-                if(endsWith==null || urdd.role.endsWith(endsWith)) {
+        for (UserRoleDAO.Data urdd : urd.value) {
+            if (full) {
+                if (endsWith==null || urdd.role.endsWith(endsWith)) {
                     RoleDAO.Data rd = RoleDAO.Data.decode(urdd);
                     Result<NsDAO.Data> nsd = ques.mayUser(trans, user, rd, Access.read);
-                    if(nsd.isOK()) {
+                    if (nsd.isOK()) {
                         Namespace namespace = lm.get(nsd.value.name);
-                        if(namespace==null) {
+                        if (namespace==null) {
                             namespace = new Namespace(nsd.value);
                             lm.put(namespace.name,namespace);
                         }
                         Result<List<String>> rls = func.getAdmins(trans, namespace.name, false);
-                        if(rls.isOK()) {
+                        if (rls.isOK()) {
                             namespace.admin=rls.value;
                         }
-                        
+
                         rls = func.getOwners(trans, namespace.name, false);
-                        if(rls.isOK()) {
+                        if (rls.isOK()) {
                             namespace.owner=rls.value;
                         }
                     }
                 }
             } else { // Shortened version.  Only Namespace Info available from Role.
-                if(Question.ADMIN.equals(urdd.rname) || Question.OWNER.equals(urdd.rname)) {
+                if (Question.ADMIN.equals(urdd.rname) || Question.OWNER.equals(urdd.rname)) {
                     RoleDAO.Data rd = RoleDAO.Data.decode(urdd);
                     Result<NsDAO.Data> nsd = ques.mayUser(trans, user, rd, Access.read);
-                    if(nsd.isOK()) {
+                    if (nsd.isOK()) {
                         Namespace namespace = lm.get(nsd.value.name);
-                        if(namespace==null) {
-                            if(other!=null) {
+                        if (namespace==null) {
+                            if (other!=null) {
                                 namespace = other.remove(nsd.value.name);
                             }
-                            if(namespace==null) {
+                            if (namespace==null) {
                                 namespace = new Namespace(nsd.value);
                                 namespace.admin=new ArrayList<>();
                                 namespace.owner=new ArrayList<>();
                             }
-                            if(endsWith==null || urdd.role.endsWith(endsWith)) {
+                            if (endsWith==null || urdd.role.endsWith(endsWith)) {
                                 lm.put(namespace.name,namespace);
-                            } else { 
+                            } else {
                                 other.put(namespace.name,namespace);
                             }
                         }
-                        if(Question.OWNER.equals(urdd.rname)) {
+                        if (Question.OWNER.equals(urdd.rname)) {
                             namespace.owner.add(urdd.user);
                         } else {
                             namespace.admin.add(urdd.user);
@@ -626,12 +636,12 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     @ApiDoc(
-            method = GET,  
+            method = GET,
             path = "/authz/nss/responsible/:id",
             params = {     "id|string|true" },
             expectedCode = 200,
-            errorCodes = { 403,404 }, 
-            text = {     "Lists all Namespaces where Identity :id is a Responsible Party", 
+            errorCodes = { 403,404 },
+            text = {     "Lists all Namespaces where Identity :id is a Responsible Party",
                         "Note: :id must be fully qualified (i.e. ab1234@people.osaaf.org)"
                     }
             )
@@ -642,58 +652,58 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             return Result.err(Status.ERR_BadData, v.errs());
         }
         Result<Collection<Namespace>> rn = loadNamepace(trans, user, ".owner",full);
-        if(rn.notOK()) {
+        if (rn.notOK()) {
             return Result.err(rn);
         }
         if (rn.isEmpty()) {
-            return Result.err(Status.ERR_NotFound, "[%s] is not an owner for any namespaces",user);        
+            return Result.err(Status.ERR_NotFound, "[%s] is not an owner for any namespaces",user);
         }
         NSS nss = mapper.newInstance(API.NSS);
         // Note: "loadNamespace" prevalidates
         return mapper.nss(trans, rn.value, nss);
     }
-    
+
     @ApiDoc(
-            method = GET,  
+            method = GET,
             path = "/authz/nss/children/:id",
             params = {     "id|string|true" },
             expectedCode = 200,
-            errorCodes = { 403,404 }, 
-            text = {     "Lists all Child Namespaces of Namespace :id", 
+            errorCodes = { 403,404 },
+            text = {     "Lists all Child Namespaces of Namespace :id",
                         "Note: This is not a cached read"
                     }
             )
     @Override
     public Result<NSS> getNSsChildren(AuthzTrans trans, String parent) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("NS", parent).err())  {
+        if (v.nullOrBlank("NS", parent).err())  {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         Result<NsDAO.Data> rnd = ques.deriveNs(trans, parent);
-        if(rnd.notOK()) {
+        if (rnd.notOK()) {
             return Result.err(rnd);
         }
         rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
-        if(rnd.notOK()) {
-            return Result.err(rnd); 
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
 
         Set<Namespace> lm = new HashSet<>();
-        Result<List<NsDAO.Data>> rlnd = ques.nsDAO.dao().getChildren(trans, parent);
-        if(rlnd.isOK()) {
-            if(rlnd.isEmpty()) {
+        Result<List<NsDAO.Data>> rlnd = ques.nsDAO().dao().getChildren(trans, parent);
+        if (rlnd.isOK()) {
+            if (rlnd.isEmpty()) {
                 return Result.err(Status.ERR_NotFound, "No data found for %s",parent);
             }
-            for(NsDAO.Data ndd : rlnd.value) {
+            for (NsDAO.Data ndd : rlnd.value) {
                 Namespace namespace = new Namespace(ndd);
                 Result<List<String>> rls = func.getAdmins(trans, namespace.name, false);
-                if(rls.isOK()) {
+                if (rls.isOK()) {
                     namespace.admin=rls.value;
                 }
-                
+
                 rls = func.getOwners(trans, namespace.name, false);
-                if(rls.isOK()) {
+                if (rls.isOK()) {
                     namespace.owner=rls.value;
                 }
 
@@ -708,11 +718,11 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
 
 
     @ApiDoc(
-            method = PUT,  
+            method = PUT,
             path = "/authz/ns",
             params = {},
             expectedCode = 200,
-            errorCodes = { 403,404,406 }, 
+            errorCodes = { 403,404,406 },
             text = { "Replace the Current Description of a Namespace with a new one"
                     }
             )
@@ -720,43 +730,43 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> updateNsDescription(AuthzTrans trans, REQUEST from) {
         final Result<Namespace> nsd = mapper.ns(trans, from);
         final ServiceValidator v = new ServiceValidator();
-        if(v.ns(nsd).err()) {
+        if (v.ns(nsd).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        if(v.nullOrBlank("description", nsd.value.description).err()) {
+        if (v.nullOrBlank("description", nsd.value.description).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Namespace namespace = nsd.value;
-        Result<List<NsDAO.Data>> rlnd = ques.nsDAO.read(trans, namespace.name);
-        
-        if(rlnd.notOKorIsEmpty()) {
+        Result<List<NsDAO.Data>> rlnd = ques.nsDAO().read(trans, namespace.name);
+
+        if (rlnd.notOKorIsEmpty()) {
             return Result.err(Status.ERR_NotFound, "Namespace [%s] does not exist",namespace.name);
         }
-        
+
         if (ques.mayUser(trans, trans.user(), rlnd.value.get(0), Access.write).notOK()) {
             return Result.err(Status.ERR_Denied, "You do not have approval to change %s",namespace.name);
         }
 
-        Result<Void> rdr = ques.nsDAO.dao().addDescription(trans, namespace.name, namespace.description);
-        if(rdr.isOK()) {
+        Result<Void> rdr = ques.nsDAO().dao().addDescription(trans, namespace.name, namespace.description);
+        if (rdr.isOK()) {
             return Result.ok();
         } else {
             return Result.err(rdr);
         }
     }
-    
+
     /**
      * deleteNS
-     * @throws DAOException 
+     * @throws DAOException
      * @see org.onap.aaf.auth.service.AuthzService#deleteNS(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.String, java.lang.String)
      */
     @ApiDoc(
-            method = DELETE,  
+            method = DELETE,
             path = "/authz/ns/:ns",
             params = {     "ns|string|true" },
             expectedCode = 200,
-            errorCodes = { 403,404,424 }, 
+            errorCodes = { 403,404,424 },
             text = {     "Delete the Namespace :ns. Namespaces cannot normally be deleted when there ",
                         "are still credentials associated with them, but they can be deleted by setting ",
                         "the \"force\" property. To do this: Add 'force=true' as a query parameter",
@@ -773,19 +783,19 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
 
 
 /***********************************
- * PERM 
+ * PERM
  ***********************************/
 
     /*
      * (non-Javadoc)
      * @see org.onap.aaf.auth.service.AuthzService#createOrUpdatePerm(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object, boolean, java.lang.String, java.lang.String, java.lang.String, java.util.List, java.util.List)
      */
-    @ApiDoc( 
-            method = POST,  
+    @ApiDoc(
+            method = POST,
             path = "/authz/perm",
             params = {},
             expectedCode = 201,
-            errorCodes = {403,404,406,409}, 
+            errorCodes = {403,404,406,409},
             text = { "Permission consists of:",
                      "<ul><li>type - a Namespace qualified identifier specifying what kind of resource "
                      + "is being protected</li>",
@@ -796,164 +806,237 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                      }
             )
     @Override
-    public Result<Void> createPerm(final AuthzTrans trans,REQUEST rreq) {        
+    public Result<Void> createPerm(final AuthzTrans trans,REQUEST rreq) {
         final Result<PermDAO.Data> newPd = mapper.perm(trans, rreq);
+
         final ServiceValidator v = new ServiceValidator();
-        if(v.perm(newPd).err()) {
+        if (v.perm(newPd).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
-        Result<FutureDAO.Data> fd = mapper.future(trans, PermDAO.TABLE, rreq, newPd.value,false,
-            new Mapper.Memo() {
-                @Override
-                public String get() {
-                    return "Create Permission [" + 
-                        newPd.value.fullType() + '|' + 
-                        newPd.value.instance + '|' + 
-                        newPd.value.action + ']';
+
+        // User Permission mechanism
+        if(newPd.value.ns.indexOf('@')>0) {
+            PermDAO.Data pdd = newPd.value;
+            if(trans.user().equals(newPd.value.ns)) {
+                CachedPermDAO permDAO = ques.permDAO();
+                Result<List<PermDAO.Data>> rlpdd = permDAO.read(trans, pdd);
+                if(rlpdd.notOK()) {
+                    return Result.err(rlpdd);
                 }
-            },
-            new MayChange() {
-                private Result<NsDAO.Data> nsd;
-                @Override
-                public Result<?> mayChange() {
-                    if(nsd==null) {
-                        nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write);
-                    }
-                    return nsd;
+                if(!rlpdd.isEmpty()) {
+                    return Result.err(Result.ERR_ConflictAlreadyExists,"Permission already exists");
                 }
-            });
-        Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, newPd.value.ns);
-        if(nsr.notOKorIsEmpty()) {
-            return Result.err(nsr);
-        }
-        switch(fd.status) {
-            case OK:
-                Result<String> rfc = func.createFuture(trans,fd.value, 
-                        newPd.value.fullType() + '|' + newPd.value.instance + '|' + newPd.value.action,
-                        trans.user(),
-                        nsr.value.get(0),
-                        FUTURE_OP.C);
-                if(rfc.isOK()) {
-                    return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing",
-                            newPd.value.ns,
-                            newPd.value.type,
-                            newPd.value.instance,
-                            newPd.value.action);
+
+                RoleDAO.Data rdd = new RoleDAO.Data();
+                rdd.ns = pdd.ns;
+                rdd.name = "user";
+
+                pdd.roles(true).add(rdd.fullName());
+                Result<PermDAO.Data> rpdd = permDAO.create(trans, pdd);
+                if(rpdd.notOK()) {
+                    return Result.err(rpdd);
+                }
+
+                CachedRoleDAO roleDAO = ques.roleDAO();
+                Result<List<RoleDAO.Data>> rlrdd = roleDAO.read(trans, rdd);
+                if(rlrdd.notOK()) {
+                    return Result.err(rlrdd);
                 } else {
-                    return Result.err(rfc);
+                    if(!rlrdd.isEmpty()) {
+                        rdd = rlrdd.value.get(0);
+                    }
                 }
-            case Status.ACC_Now:
-                return func.createPerm(trans, newPd.value, true);
-            default:
-                return Result.err(fd);
-        }    
+
+                String eperm = pdd.encode();
+                rdd.perms(true).add(eperm);
+                Result<Void> rv = roleDAO.update(trans, rdd);
+                if(rv.notOK()) {
+                    return rv;
+                }
+
+                CachedUserRoleDAO urDAO = ques.userRoleDAO();
+                UserRoleDAO.Data urdd = new UserRoleDAO.Data();
+                urdd.user = trans.user();
+                urdd.ns = rdd.ns;
+                urdd.rname = rdd.name;
+                urdd.role = rdd.fullName();
+                Result<List<UserRoleDAO.Data>> rlurdd = urDAO.read(trans, urdd);
+                if(rlurdd.notOK()) {
+                    return Result.err(rlrdd);
+                } else if(rlurdd.isEmpty()) {
+                    GregorianCalendar gc = trans.org().expiration(null, Expiration.UserInRole);
+                    if(gc==null) {
+                        return Result.err(Result.ERR_Policy,"Organzation does not grant Expiration for UserRole");
+                    } else {
+                        urdd.expires = gc.getTime();
+                    }
+                    Result<UserRoleDAO.Data> rurdd = urDAO.create(trans, urdd);
+                    return Result.err(rurdd);
+                }
+                return rv;
+            } else {
+                return Result.err(Result.ERR_Security,"Only the User can create User Permissions");
+            }
+        } else {
+            // Does Perm Type exist as a Namespace?
+            if(newPd.value.type.isEmpty() || ques.nsDAO().read(trans, newPd.value.fullType()).isOKhasData()) {
+                return Result.err(Status.ERR_ConflictAlreadyExists,
+                        "Permission Type exists as a Namespace");
+            }
+
+            Result<FutureDAO.Data> fd = mapper.future(trans, PermDAO.TABLE, rreq, newPd.value,false,
+                new Mapper.Memo() {
+                    @Override
+                    public String get() {
+                        return "Create Permission [" +
+                            newPd.value.fullType() + '|' +
+                            newPd.value.instance + '|' +
+                            newPd.value.action + ']';
+                    }
+                },
+                new MayChange() {
+                    private Result<NsDAO.Data> nsd;
+                    @Override
+                    public Result<?> mayChange() {
+                        if (nsd==null) {
+                            nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write);
+                        }
+                        return nsd;
+                    }
+                });
+
+            Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, newPd.value.ns);
+            if (nsr.notOKorIsEmpty()) {
+                return Result.err(nsr);
+            }
+            switch(fd.status) {
+                case OK:
+                    Result<String> rfc = func.createFuture(trans,fd.value,
+                            newPd.value.fullType() + '|' + newPd.value.instance + '|' + newPd.value.action,
+                            trans.user(),
+                            nsr.value.get(0),
+                            FUTURE_OP.C);
+                    if (rfc.isOK()) {
+                        return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing",
+                                newPd.value.ns,
+                                newPd.value.type,
+                                newPd.value.instance,
+                                newPd.value.action);
+                    } else {
+                        return Result.err(rfc);
+                    }
+                case Status.ACC_Now:
+                    return func.createPerm(trans, newPd.value, true);
+                default:
+                    return Result.err(fd);
+            }
+        }
     }
 
-    @ApiDoc( 
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authz/perms/:type",
             params = {"type|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "List All Permissions that match the :type element of the key" }
             )
     @Override
     public Result<PERMS> getPermsByType(AuthzTrans trans, final String permType) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("PermType", permType).err()) {
+        if (v.nullOrBlank("PermType", permType).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<List<PermDAO.Data>> rlpd = ques.getPermsByType(trans, permType);
-        if(rlpd.notOK()) {
+        if (rlpd.notOK()) {
             return Result.err(rlpd);
         }
 
 //        We don't have instance & action for mayUserView... do we want to loop through all returned here as well as in mapper?
 //        Result<NsDAO.Data> r;
-//        if((r = ques.mayUserViewPerm(trans, trans.user(), permType)).notOK())return Result.err(r);
-        
+//        if ((r = ques.mayUserViewPerm(trans, trans.user(), permType)).notOK())return Result.err(r);
+
         PERMS perms = mapper.newInstance(API.PERMS);
-        if(!rlpd.isEmpty()) {
+        if (!rlpd.isEmpty()) {
             // Note: Mapper will restrict what can be viewed
             return mapper.perms(trans, rlpd.value, perms, true);
         }
         return Result.ok(perms);
     }
-    
-    @ApiDoc( 
-            method = GET,  
+
+    @ApiDoc(
+            method = GET,
             path = "/authz/perms/:type/:instance/:action",
             params = {"type|string|true",
                       "instance|string|true",
                       "action|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "List Permissions that match key; :type, :instance and :action" }
             )
     @Override
     public Result<PERMS> getPermsByName(AuthzTrans trans, String type, String instance, String action) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("PermType", type).err()
+        if (v.nullOrBlank("PermType", type).err()
                 || v.nullOrBlank("PermInstance", instance).err()
                 || v.nullOrBlank("PermAction", action).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         Result<List<PermDAO.Data>> rlpd = ques.getPermsByName(trans, type, instance, action);
-        if(rlpd.notOK()) {
+        if (rlpd.notOK()) {
             return Result.err(rlpd);
         }
 
         PERMS perms = mapper.newInstance(API.PERMS);
-        if(!rlpd.isEmpty()) {
+        if (!rlpd.isEmpty()) {
             // Note: Mapper will restrict what can be viewed
             return mapper.perms(trans, rlpd.value, perms, true);
         }
         return Result.ok(perms);
     }
 
-    @ApiDoc( 
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authz/perms/user/:user",
             params = {"user|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "List All Permissions that match user :user",
                      "<p>'user' must be expressed as full identity (ex: id@full.domain.com)</p>"}
             )
     @Override
     public Result<PERMS> getPermsByUser(AuthzTrans trans, String user) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User", user).err()) {
+        if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
-        Result<List<PermDAO.Data>> rlpd = ques.getPermsByUser(trans, user, 
-                trans.requested(force));
-        if(rlpd.notOK()) {
+        PermLookup pl = PermLookup.get(trans,ques,user);
+        Result<List<PermDAO.Data>> rlpd = pl.getPerms(trans.requested(force));
+        if (rlpd.notOK()) {
             return Result.err(rlpd);
         }
-        
+
         PERMS perms = mapper.newInstance(API.PERMS);
-        
-        if(rlpd.isEmpty()) {
+
+        if (rlpd.isEmpty()) {
             return Result.ok(perms);
         }
         // Note: Mapper will restrict what can be viewed
         //   if user is the same as that which is looked up, no filtering is required
-        return mapper.perms(trans, rlpd.value, 
-                perms, 
+        return mapper.perms(trans, rlpd.value,
+                perms,
                 !user.equals(trans.user()));
     }
 
-    @ApiDoc( 
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authz/perms/user/:user/scope/:scope",
             params = {"user|string|true","scope|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "List All Permissions that match user :user, filtered by NS (Scope)",
                      "<p>'user' must be expressed as full identity (ex: id@full.domain.com)</p>",
                      "<p>'scope' must be expressed as NSs separated by ':'</p>"
@@ -962,34 +1045,34 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<PERMS> getPermsByUserScope(AuthzTrans trans, String user, String[] scopes) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User", user).err()) {
+        if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<List<PermDAO.Data>> rlpd = ques.getPermsByUser(trans, user, trans.requested(force));
-        if(rlpd.notOK()) {
+        if (rlpd.notOK()) {
             return Result.err(rlpd);
         }
-        
+
         PERMS perms = mapper.newInstance(API.PERMS);
-        
-        if(rlpd.isEmpty()) {
+
+        if (rlpd.isEmpty()) {
             return Result.ok(perms);
         }
         // Note: Mapper will restrict what can be viewed
         //   if user is the same as that which is looked up, no filtering is required
-        return mapper.perms(trans, rlpd.value, 
-                perms, 
+        return mapper.perms(trans, rlpd.value,
+                perms,
                 scopes,
                 !user.equals(trans.user()));
     }
 
-    @ApiDoc( 
-            method = POST,  
+    @ApiDoc(
+            method = POST,
             path = "/authz/perms/user/:user",
             params = {"user|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "List All Permissions that match user :user",
                      "<p>'user' must be expressed as full identity (ex: id@full.domain.com)</p>",
                      "",
@@ -1014,40 +1097,41 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<PERMS> getPermsByUser(AuthzTrans trans, PERMS _perms, String user) {
             PERMS perms = _perms;
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User", user).err()) {
+        if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         //////////////
-        Result<List<PermDAO.Data>> rlpd = ques.getPermsByUser(trans, user,trans.requested(force));
-        if(rlpd.notOK()) {
+        PermLookup pl = PermLookup.get(trans,ques,user);
+        Result<List<PermDAO.Data>> rlpd = pl.getPerms(trans.requested(force));
+        if (rlpd.notOK()) {
             return Result.err(rlpd);
         }
-        
-        /*//TODO 
+
+        /*//TODO
           1) See if allowed to query
           2) See if User is allowed
           */
         Result<List<PermDAO.Data>> in = mapper.perms(trans, perms);
-        if(in.isOKhasData()) {
+        if (in.isOKhasData()) {
             List<PermDAO.Data> out = rlpd.value;
             boolean ok;
-            for(PermDAO.Data pdd : in.value) {
+            for (PermDAO.Data pdd : in.value) {
                 ok = false;
-                if("access".equals(pdd.type)) {
+                if ("access".equals(pdd.type)) {
                     Access access = Access.valueOf(pdd.action);
                     String[] mdkey = Split.splitTrim(':',pdd.instance);
-                    if(mdkey.length>1) {
+                    if (mdkey.length>1) {
                         String type = mdkey[1];
-                        if("role".equals(type)) {
-                            if(mdkey.length>2) {
+                        if ("role".equals(type)) {
+                            if (mdkey.length>2) {
                                 RoleDAO.Data rdd = new RoleDAO.Data();
                                 rdd.ns=pdd.ns;
                                 rdd.name=mdkey[2];
                                 ok = ques.mayUser(trans, trans.user(), rdd, Access.read).isOK() && ques.mayUser(trans, user, rdd , access).isOK();
                             }
-                        } else if("perm".equals(type)) {
-                            if(mdkey.length>4) { // also need instance/action
+                        } else if ("perm".equals(type)) {
+                            if (mdkey.length>4) { // also need instance/action
                                 PermDAO.Data p = new PermDAO.Data();
                                 p.ns=pdd.ns;
                                 p.type=mdkey[2];
@@ -1055,111 +1139,111 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                                 p.action=mdkey[4];
                                 ok = ques.mayUser(trans, trans.user(), p, Access.read).isOK() && ques.mayUser(trans, user, p , access).isOK();
                             }
-                        } else if("ns".equals(type)) {
+                        } else if ("ns".equals(type)) {
                             NsDAO.Data ndd = new NsDAO.Data();
                             ndd.name=pdd.ns;
                             ok = ques.mayUser(trans, trans.user(), ndd, Access.read).isOK() && ques.mayUser(trans, user, ndd , access).isOK();
                         }
                     }
                 }
-                if(ok) {
+                if (ok) {
                     out.add(pdd);
                 }
             }
-        }        
-        
+        }
+
         perms = mapper.newInstance(API.PERMS);
-        if(rlpd.isEmpty()) {
+        if (rlpd.isEmpty()) {
             return Result.ok(perms);
         }
         // Note: Mapper will restrict what can be viewed
         //   if user is the same as that which is looked up, no filtering is required
-        return mapper.perms(trans, rlpd.value, 
-                perms, 
+        return mapper.perms(trans, rlpd.value,
+                perms,
                 !user.equals(trans.user()));
     }
-    
-    @ApiDoc( 
-            method = GET,  
+
+    @ApiDoc(
+            method = GET,
             path = "/authz/perms/role/:role",
             params = {"role|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "List All Permissions that are granted to :role" }
             )
     @Override
     public Result<PERMS> getPermsByRole(AuthzTrans trans,String role) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Role", role).err()) {
+        if (v.nullOrBlank("Role", role).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans, ques,role);
-        if(rrdd.notOK()) {
+        if (rrdd.notOK()) {
             return Result.err(rrdd);
         }
 
         Result<NsDAO.Data> r = ques.mayUser(trans, trans.user(), rrdd.value, Access.read);
-        if(r.notOK()) {
+        if (r.notOK()) {
             return Result.err(r);
         }
 
         PERMS perms = mapper.newInstance(API.PERMS);
 
         Result<List<PermDAO.Data>> rlpd = ques.getPermsByRole(trans, role, trans.requested(force));
-        if(rlpd.isOKhasData()) {
+        if (rlpd.isOKhasData()) {
             // Note: Mapper will restrict what can be viewed
             return mapper.perms(trans, rlpd.value, perms, true);
         }
         return Result.ok(perms);
     }
 
-    @ApiDoc( 
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authz/perms/ns/:ns",
             params = {"ns|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "List All Permissions that are in Namespace :ns" }
             )
     @Override
     public Result<PERMS> getPermsByNS(AuthzTrans trans,String ns) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("NS", ns).err()) {
+        if (v.nullOrBlank("NS", ns).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<NsDAO.Data> rnd = ques.deriveNs(trans, ns);
-        if(rnd.notOK()) {
+        if (rnd.notOK()) {
             return Result.err(rnd);
         }
 
         rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
-        if(rnd.notOK()) {
-            return Result.err(rnd);     
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
-        
-        Result<List<PermDAO.Data>> rlpd = ques.permDAO.readNS(trans, ns);
-        if(rlpd.notOK()) {
+
+        Result<List<PermDAO.Data>> rlpd = ques.permDAO().readNS(trans, ns);
+        if (rlpd.notOK()) {
             return Result.err(rlpd);
         }
 
         PERMS perms = mapper.newInstance(API.PERMS);
-        if(!rlpd.isEmpty()) {
+        if (!rlpd.isEmpty()) {
             // Note: Mapper will restrict what can be viewed
             return mapper.perms(trans, rlpd.value,perms, true);
         }
         return Result.ok(perms);
     }
-    
-    @ApiDoc( 
-            method = PUT,  
+
+    @ApiDoc(
+            method = PUT,
             path =     "/authz/perm/:type/:instance/:action",
             params = {"type|string|true",
                       "instance|string|true",
                         "action|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406, 409 }, 
+            errorCodes = { 404,406, 409 },
             text = { "Rename the Permission referenced by :type :instance :action, and "
                     + "rename (copy/delete) to the Permission described in PermRequest" }
             )
@@ -1167,7 +1251,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> renamePerm(final AuthzTrans trans,REQUEST rreq, String origType, String origInstance, String origAction) {
         final Result<PermDAO.Data> newPd = mapper.perm(trans, rreq);
         final ServiceValidator v = new ServiceValidator();
-        if(v.perm(newPd).err()) {
+        if (v.perm(newPd).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
@@ -1175,68 +1259,68 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             return Result.err(Status.ERR_Denied, "You do not have approval to change Permission [%s.%s|%s|%s]",
                     newPd.value.ns,newPd.value.type,newPd.value.instance,newPd.value.action);
         }
-        
+
         Result<NsSplit> nss = ques.deriveNsSplit(trans, origType);
-        Result<List<PermDAO.Data>> origRlpd = ques.permDAO.read(trans, nss.value.ns, nss.value.name, origInstance, origAction); 
-        
-        if(origRlpd.notOKorIsEmpty()) {
-            return Result.err(Status.ERR_PermissionNotFound, 
+        Result<List<PermDAO.Data>> origRlpd = ques.permDAO().read(trans, nss.value.ns, nss.value.name, origInstance, origAction);
+
+        if (origRlpd.notOKorIsEmpty()) {
+            return Result.err(Status.ERR_PermissionNotFound,
                     "Permission [%s|%s|%s] does not exist",
                     origType,origInstance,origAction);
         }
-        
+
         PermDAO.Data origPd = origRlpd.value.get(0);
 
         if (!origPd.ns.equals(newPd.value.ns)) {
             return Result.err(Status.ERR_Denied, "Cannot change namespace with rename command. " +
                     "<new type> must start with [" + origPd.ns + "]");
         }
-        
-        if ( origPd.type.equals(newPd.value.type) && 
-                origPd.action.equals(newPd.value.action) && 
+
+        if ( origPd.type.equals(newPd.value.type) &&
+                origPd.action.equals(newPd.value.action) &&
                 origPd.instance.equals(newPd.value.instance) ) {
             return Result.err(Status.ERR_ConflictAlreadyExists, "New Permission must be different than original permission");
         }
-        
+
         Set<String> origRoles = origPd.roles(false);
         if (!origRoles.isEmpty()) {
             Set<String> roles = newPd.value.roles(true);
             for (String role : origPd.roles) {
-                roles.add(role); 
+                roles.add(role);
             }
-        }    
-        
+        }
+
         newPd.value.description = origPd.description;
-        
+
         Result<Void> rv = null;
-        
+
         rv = func.createPerm(trans, newPd.value, false);
         if (rv.isOK()) {
             rv = func.deletePerm(trans, origPd, true, false);
         }
         return rv;
     }
-    
-    @ApiDoc( 
-            method = PUT,  
+
+    @ApiDoc(
+            method = PUT,
             path = "/authz/perm",
             params = {},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "Add Description Data to Perm" }
             )
     @Override
     public Result<Void> updatePermDescription(AuthzTrans trans, REQUEST from) {
         final Result<PermDAO.Data> pd = mapper.perm(trans, from);
         final ServiceValidator v = new ServiceValidator();
-        if(v.perm(pd).err()) {
+        if (v.perm(pd).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        if(v.nullOrBlank("description", pd.value.description).err()) {
+        if (v.nullOrBlank("description", pd.value.description).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         final PermDAO.Data perm = pd.value;
-        if(ques.permDAO.read(trans, perm.ns, perm.type, perm.instance,perm.action).notOKorIsEmpty()) {
+        if (ques.permDAO().read(trans, perm.ns, perm.type, perm.instance,perm.action).notOKorIsEmpty()) {
             return Result.err(Status.ERR_NotFound, "Permission [%s.%s|%s|%s] does not exist",
                 perm.ns,perm.type,perm.instance,perm.action);
         }
@@ -1246,21 +1330,21 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     perm.ns,perm.type,perm.instance,perm.action);
         }
 
-        Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, pd.value.ns);
-        if(nsr.notOKorIsEmpty()) {
+        Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, pd.value.ns);
+        if (nsr.notOKorIsEmpty()) {
             return Result.err(nsr);
         }
 
-        Result<Void> rdr = ques.permDAO.addDescription(trans, perm.ns, perm.type, perm.instance,
+        Result<Void> rdr = ques.permDAO().addDescription(trans, perm.ns, perm.type, perm.instance,
                 perm.action, perm.description);
-        if(rdr.isOK()) {
+        if (rdr.isOK()) {
             return Result.ok();
         } else {
             return Result.err(rdr);
         }
 
     }
-    
+
     @ApiDoc(
             method = PUT,
             path = "/authz/role/perm",
@@ -1273,12 +1357,12 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<Void> resetPermRoles(final AuthzTrans trans, REQUEST rreq) {
         final Result<PermDAO.Data> updt = mapper.permFromRPRequest(trans, rreq);
-        if(updt.notOKorIsEmpty()) {
+        if (updt.notOKorIsEmpty()) {
             return Result.err(updt);
         }
 
         final ServiceValidator v = new ServiceValidator();
-        if(v.perm(updt).err()) {
+        if (v.perm(updt).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
@@ -1288,24 +1372,24 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         }
 
         // Read full set to get CURRENT values
-        Result<List<PermDAO.Data>> rcurr = ques.permDAO.read(trans, 
-                updt.value.ns, 
-                updt.value.type, 
-                updt.value.instance, 
+        Result<List<PermDAO.Data>> rcurr = ques.permDAO().read(trans,
+                updt.value.ns,
+                updt.value.type,
+                updt.value.instance,
                 updt.value.action);
-        
-        if(rcurr.notOKorIsEmpty()) {
-            return Result.err(Status.ERR_PermissionNotFound, 
+
+        if (rcurr.notOKorIsEmpty()) {
+            return Result.err(Status.ERR_PermissionNotFound,
                     "Permission [%s.%s|%s|%s] does not exist",
                      updt.value.ns,updt.value.type,updt.value.instance,updt.value.action);
         }
-        
+
         // Create a set of Update Roles, which are in Internal Format
         Set<String> updtRoles = new HashSet<>();
         Result<NsSplit> nss;
-        for(String role : updt.value.roles(false)) {
+        for (String role : updt.value.roles(false)) {
             nss = ques.deriveNsSplit(trans, role);
-            if(nss.isOK()) {
+            if (nss.isOK()) {
                 updtRoles.add(nss.value.ns + '|' + nss.value.name);
             } else {
                 trans.error().log(nss.errorString());
@@ -1313,18 +1397,18 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         }
 
         Result<Void> rv = null;
-        
-        for(PermDAO.Data curr : rcurr.value) {
+
+        for (PermDAO.Data curr : rcurr.value) {
             Set<String> currRoles = curr.roles(false);
-            // must add roles to this perm, and add this perm to each role 
-            // in the update, but not in the current            
+            // must add roles to this perm, and add this perm to each role
+            // in the update, but not in the current
             for (String role : updtRoles) {
                 if (!currRoles.contains(role)) {
                     Result<RoleDAO.Data> key = RoleDAO.Data.decode(trans, ques, role);
-                    if(key.isOKhasData()) {
-                        Result<List<RoleDAO.Data>> rrd = ques.roleDAO.read(trans, key.value);
-                        if(rrd.isOKhasData()) {
-                            for(RoleDAO.Data r : rrd.value) {
+                    if (key.isOKhasData()) {
+                        Result<List<RoleDAO.Data>> rrd = ques.roleDAO().read(trans, key.value);
+                        if (rrd.isOKhasData()) {
+                            for (RoleDAO.Data r : rrd.value) {
                                 rv = func.addPermToRole(trans, r, curr, false);
                                 if (rv.notOK() && rv.status!=Result.ERR_ConflictAlreadyExists) {
                                     return Result.err(rv);
@@ -1341,10 +1425,10 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             for (String role : currRoles) {
                 if (!updtRoles.contains(role)) {
                     Result<RoleDAO.Data> key = RoleDAO.Data.decode(trans, ques, role);
-                    if(key.isOKhasData()) {
-                        Result<List<RoleDAO.Data>> rdd = ques.roleDAO.read(trans, key.value);
-                        if(rdd.isOKhasData()) {
-                            for(RoleDAO.Data r : rdd.value) {
+                    if (key.isOKhasData()) {
+                        Result<List<RoleDAO.Data>> rdd = ques.roleDAO().read(trans, key.value);
+                        if (rdd.isOKhasData()) {
+                            for (RoleDAO.Data r : rdd.value) {
                                 rv = func.delPermFromRole(trans, r, curr, true);
                                 if (rv.notOK() && rv.status!=Status.ERR_PermissionNotFound) {
                                     return Result.err(rv);
@@ -1353,17 +1437,17 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                         }
                     }
                 }
-            }                
-        } 
-        return rv==null?Result.ok():rv;        
+            }
+        }
+        return rv==null?Result.ok():rv;
     }
-    
-    @ApiDoc( 
+
+    @ApiDoc(
             method = DELETE,
             path = "/authz/perm",
             params = {},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "Delete the Permission referenced by PermKey.",
                     "You cannot normally delete a permission which is still granted to roles,",
                     "however the \"force\" property allows you to do just that. To do this: Add",
@@ -1373,15 +1457,15 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<Void> deletePerm(final AuthzTrans trans, REQUEST from) {
         Result<PermDAO.Data> pd = mapper.perm(trans, from);
-        if(pd.notOK()) {
+        if (pd.notOK()) {
             return Result.err(pd);
         }
         final ServiceValidator v = new ServiceValidator();
-        if(v.nullOrBlank(pd.value).err()) {
+        if (v.nullOrBlank(pd.value).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         final PermDAO.Data perm = pd.value;
-        if (ques.permDAO.read(trans, perm).notOKorIsEmpty()) {
+        if (ques.permDAO().read(trans, perm).notOKorIsEmpty()) {
             return Result.err(Status.ERR_PermissionNotFound, "Permission [%s.%s|%s|%s] does not exist",
                     perm.ns,perm.type,perm.instance,perm.action    );
         }
@@ -1397,42 +1481,42 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                 private Result<NsDAO.Data> nsd;
                 @Override
                 public Result<?> mayChange() {
-                    if(nsd==null) {
+                    if (nsd==null) {
                         nsd = ques.mayUser(trans, trans.user(), perm, Access.write);
                     }
                     return nsd;
                 }
             });
-        
+
         switch(fd.status) {
         case OK:
-            Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, perm.ns);
-            if(nsr.notOKorIsEmpty()) {
+            Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, perm.ns);
+            if (nsr.notOKorIsEmpty()) {
                 return Result.err(nsr);
             }
-            
-            Result<String> rfc = func.createFuture(trans, fd.value, 
+
+            Result<String> rfc = func.createFuture(trans, fd.value,
                     perm.encode(), trans.user(),nsr.value.get(0),FUTURE_OP.D);
-            if(rfc.isOK()) {
+            if (rfc.isOK()) {
                 return Result.err(Status.ACC_Future, "Perm Deletion [%s] is saved for future processing",perm.encode());
-            } else { 
+            } else {
                 return Result.err(rfc);
             }
         case Status.ACC_Now:
             return func.deletePerm(trans,perm,trans.requested(force), false);
         default:
             return Result.err(fd);
-        }            
-    }    
-    
-    @ApiDoc( 
+        }
+    }
+
+    @ApiDoc(
             method = DELETE,
             path = "/authz/perm/:name/:type/:action",
             params = {"type|string|true",
                       "instance|string|true",
                           "action|string|true"},
             expectedCode = 200,
-            errorCodes = { 404,406 }, 
+            errorCodes = { 404,406 },
             text = { "Delete the Permission referenced by :type :instance :action",
                     "You cannot normally delete a permission which is still granted to roles,",
                     "however the \"force\" property allows you to do just that. To do this: Add",
@@ -1442,15 +1526,15 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<Void> deletePerm(AuthzTrans trans, String type, String instance, String action) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Type",type)
+        if (v.nullOrBlank("Type",type)
             .nullOrBlank("Instance",instance)
             .nullOrBlank("Action",action)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         Result<PermDAO.Data> pd = ques.permFrom(trans, type, instance, action);
-        if(pd.isOK()) {
+        if (pd.isOK()) {
             return func.deletePerm(trans, pd.value, trans.requested(force), false);
         } else {
             return Result.err(pd);
@@ -1458,7 +1542,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
 /***********************************
- * ROLE 
+ * ROLE
  ***********************************/
     @ApiDoc(
             method = POST,
@@ -1484,12 +1568,17 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<Void> createRole(final AuthzTrans trans, REQUEST from) {
         final Result<RoleDAO.Data> rd = mapper.role(trans, from);
+        // Does Perm Type exist as a Namespace?
+        if(rd.value.name.isEmpty() || ques.nsDAO().read(trans, rd.value.fullName()).isOKhasData()) {
+            return Result.err(Status.ERR_ConflictAlreadyExists,
+                    "Role exists as a Namespace");
+        }
         final ServiceValidator v = new ServiceValidator();
-        if(v.role(rd).err()) {
+        if (v.role(rd).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         final RoleDAO.Data role = rd.value;
-        if(ques.roleDAO.read(trans, role.ns, role.name).isOKhasData()) {
+        if (ques.roleDAO().read(trans, role.ns, role.name).isOKhasData()) {
             return Result.err(Status.ERR_ConflictAlreadyExists, "Role [" + role.fullName() + "] already exists");
         }
 
@@ -1497,8 +1586,8 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             new Mapper.Memo() {
                 @Override
                 public String get() {
-                    return "Create Role [" + 
-                        rd.value.fullName() + 
+                    return "Create Role [" +
+                        rd.value.fullName() +
                         ']';
                 }
             },
@@ -1506,32 +1595,32 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                 private Result<NsDAO.Data> nsd;
                 @Override
                 public Result<?> mayChange() {
-                    if(nsd==null) {
+                    if (nsd==null) {
                         nsd = ques.mayUser(trans, trans.user(), role, Access.write);
                     }
                     return nsd;
                 }
             });
-        
-        Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, rd.value.ns);
-        if(nsr.notOKorIsEmpty()) {
+
+        Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, rd.value.ns);
+        if (nsr.notOKorIsEmpty()) {
             return Result.err(nsr);
         }
 
         switch(fd.status) {
             case OK:
-                Result<String> rfc = func.createFuture(trans, fd.value, 
+                Result<String> rfc = func.createFuture(trans, fd.value,
                         role.encode(), trans.user(),nsr.value.get(0),FUTURE_OP.C);
-                if(rfc.isOK()) {
+                if (rfc.isOK()) {
                     return Result.err(Status.ACC_Future, "Role [%s.%s] is saved for future processing",
                             rd.value.ns,
                             rd.value.name);
-                } else { 
+                } else {
                     return Result.err(rfc);
                 }
             case Status.ACC_Now:
-                Result<RoleDAO.Data> rdr = ques.roleDAO.create(trans, role);
-                if(rdr.isOK()) {
+                Result<RoleDAO.Data> rdr = ques.roleDAO().create(trans, role);
+                if (rdr.isOK()) {
                     return Result.ok();
                 } else {
                     return Result.err(rdr);
@@ -1547,7 +1636,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @ApiDoc(
             method = GET,
             path = "/authz/roles/:role",
-            params = {"role|string|true"}, 
+            params = {"role|string|true"},
             expectedCode = 200,
             errorCodes = {404,406},
             text = { "List Roles that match :role",
@@ -1557,25 +1646,25 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<ROLES> getRolesByName(AuthzTrans trans, String role) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Role", role).err()) {
+        if (v.nullOrBlank("Role", role).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         // Determine if User can ask this question
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans, ques, role);
-        if(rrdd.isOKhasData()) {
+        if (rrdd.isOKhasData()) {
             Result<NsDAO.Data> r;
-            if((r = ques.mayUser(trans, trans.user(), rrdd.value, Access.read)).notOK()) {
+            if ((r = ques.mayUser(trans, trans.user(), rrdd.value, Access.read)).notOK()) {
                 return Result.err(r);
             }
         } else {
             return Result.err(rrdd);
         }
-        
+
         // Look up data
         int query = role.indexOf('?');
         Result<List<RoleDAO.Data>> rlrd = ques.getRolesByName(trans, query<0?role:role.substring(0, query));
-        if(rlrd.isOK()) {
+        if (rlrd.isOK()) {
             // Note: Mapper will restrict what can be viewed
             ROLES roles = mapper.newInstance(API.ROLES);
             return mapper.roles(trans, rlrd.value, roles, true);
@@ -1602,20 +1691,20 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<ROLES> getRolesByUser(AuthzTrans trans, String user) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User", user).err()) {
+        if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         ROLES roles = mapper.newInstance(API.ROLES);
         // Get list of roles per user, then add to Roles as we go
         Result<List<RoleDAO.Data>> rlrd;
-        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByUser(trans, user);
-        if(rlurd.isOKhasData()) {
-            for(UserRoleDAO.Data urd : rlurd.value ) {
-                rlrd = ques.roleDAO.read(trans, urd.ns,urd.rname);
+        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, user);
+        if (rlurd.isOKhasData()) {
+            for (UserRoleDAO.Data urd : rlurd.value ) {
+                rlrd = ques.roleDAO().read(trans, urd.ns,urd.rname);
                 // Note: Mapper will restrict what can be viewed
                 //   if user is the same as that which is looked up, no filtering is required
-                if(rlrd.isOKhasData()) {
+                if (rlrd.isOKhasData()) {
                     mapper.roles(trans, rlrd.value,roles, !user.equals(trans.user()));
                 }
             }
@@ -1633,7 +1722,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             params = {"ns|string|true"},
             expectedCode = 200,
             errorCodes = {404,406},
-            text = { "List all Roles for the Namespace :ns", 
+            text = { "List all Roles for the Namespace :ns",
                          "Note: You must have permission to see any given role"
             }
            )
@@ -1641,27 +1730,27 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<ROLES> getRolesByNS(AuthzTrans trans, String ns) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("NS", ns).err()) {
+        if (v.nullOrBlank("NS", ns).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         // check if user is allowed to view NS
-        Result<NsDAO.Data> rnsd = ques.deriveNs(trans, ns); 
-        if(rnsd.notOK()) {
-            return Result.err(rnsd);     
+        Result<NsDAO.Data> rnsd = ques.deriveNs(trans, ns);
+        if (rnsd.notOK()) {
+            return Result.err(rnsd);
         }
         rnsd = ques.mayUser(trans, trans.user(), rnsd.value, Access.read);
-        if(rnsd.notOK()) {
-            return Result.err(rnsd);     
+        if (rnsd.notOK()) {
+            return Result.err(rnsd);
         }
 
         TimeTaken tt = trans.start("MAP Roles by NS to Roles", Env.SUB);
         try {
             ROLES roles = mapper.newInstance(API.ROLES);
             // Get list of roles per user, then add to Roles as we go
-            Result<List<RoleDAO.Data>> rlrd = ques.roleDAO.readNS(trans, ns);
-            if(rlrd.isOK()) {
-                if(!rlrd.isEmpty()) {
+            Result<List<RoleDAO.Data>> rlrd = ques.roleDAO().readNS(trans, ns);
+            if (rlrd.isOK()) {
+                if (!rlrd.isEmpty()) {
                     // Note: Mapper doesn't need to restrict what can be viewed, because we did it already.
                     mapper.roles(trans,rlrd.value,roles,false);
                 }
@@ -1684,26 +1773,26 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             params = {"name|string|true"},
             expectedCode = 200,
             errorCodes = {404,406},
-            text = { "List all Roles for only the Name of Role (without Namespace)", 
+            text = { "List all Roles for only the Name of Role (without Namespace)",
                          "Note: You must have permission to see any given role"
             }
            )
     @Override
     public Result<ROLES> getRolesByNameOnly(AuthzTrans trans, String name) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Name", name).err()) {
+        if (v.nullOrBlank("Name", name).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         // User Mapper to make sure user is allowed to view NS
 
         TimeTaken tt = trans.start("MAP Roles by Name to Roles", Env.SUB);
         try {
             ROLES roles = mapper.newInstance(API.ROLES);
             // Get list of roles per user, then add to Roles as we go
-            Result<List<RoleDAO.Data>> rlrd = ques.roleDAO.readName(trans, name);
-            if(rlrd.isOK()) {
-                if(!rlrd.isEmpty()) {
+            Result<List<RoleDAO.Data>> rlrd = ques.roleDAO().readName(trans, name);
+            if (rlrd.isOK()) {
+                if (!rlrd.isEmpty()) {
                     // Note: Mapper will restrict what can be viewed
                     mapper.roles(trans,rlrd.value,roles,true);
                 }
@@ -1739,34 +1828,34 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<ROLES> getRolesByPerm(AuthzTrans trans, String type, String instance, String action) {
         final Validator v = new ServiceValidator();
-        if(v.permType(type)
+        if (v.permType(type)
             .permInstance(instance)
             .permAction(action)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         TimeTaken tt = trans.start("Map Perm Roles Roles", Env.SUB);
         try {
             ROLES roles = mapper.newInstance(API.ROLES);
             // Get list of roles per user, then add to Roles as we go
             Result<NsSplit> nsSplit = ques.deriveNsSplit(trans, type);
-            if(nsSplit.isOK()) {
+            if (nsSplit.isOK()) {
                 PermDAO.Data pdd = new PermDAO.Data(nsSplit.value, instance, action);
                 Result<?> res;
-                if((res=ques.mayUser(trans, trans.user(), pdd, Question.Access.read)).notOK()) {
+                if ((res=ques.mayUser(trans, trans.user(), pdd, Question.Access.read)).notOK()) {
                     return Result.err(res);
                 }
-                
-                Result<List<PermDAO.Data>> pdlr = ques.permDAO.read(trans, pdd);
-                if(pdlr.isOK())for(PermDAO.Data pd : pdlr.value) {
+
+                Result<List<PermDAO.Data>> pdlr = ques.permDAO().read(trans, pdd);
+                if (pdlr.isOK())for (PermDAO.Data pd : pdlr.value) {
                     Result<List<RoleDAO.Data>> rlrd;
-                    for(String r : pd.roles) {
+                    for (String r : pd.roles) {
                         Result<String[]> rs = RoleDAO.Data.decodeToArray(trans, ques, r);
-                        if(rs.isOK()) {
-                            rlrd = ques.roleDAO.read(trans, rs.value[0],rs.value[1]);
+                        if (rs.isOK()) {
+                            rlrd = ques.roleDAO().read(trans, rs.value[0],rs.value[1]);
                             // Note: Mapper will restrict what can be viewed
-                            if(rlrd.isOKhasData()) {
+                            if (rlrd.isOKhasData()) {
                                 mapper.roles(trans,rlrd.value,roles,true);
                             }
                         }
@@ -1792,15 +1881,15 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> updateRoleDescription(AuthzTrans trans, REQUEST from) {
         final Result<RoleDAO.Data> rd = mapper.role(trans, from);
         final ServiceValidator v = new ServiceValidator();
-        if(v.role(rd).err()) {
+        if (v.role(rd).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         } {
-        if(v.nullOrBlank("description", rd.value.description).err()) {
+        if (v.nullOrBlank("description", rd.value.description).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         }
         final RoleDAO.Data role = rd.value;
-        if(ques.roleDAO.read(trans, role.ns, role.name).notOKorIsEmpty()) {
+        if (ques.roleDAO().read(trans, role.ns, role.name).notOKorIsEmpty()) {
             return Result.err(Status.ERR_NotFound, "Role [" + role.fullName() + "] does not exist");
         }
 
@@ -1808,20 +1897,20 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             return Result.err(Status.ERR_Denied, "You do not have approval to change " + role.fullName());
         }
 
-        Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, rd.value.ns);
-        if(nsr.notOKorIsEmpty()) {
+        Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, rd.value.ns);
+        if (nsr.notOKorIsEmpty()) {
             return Result.err(nsr);
         }
 
-        Result<Void> rdr = ques.roleDAO.addDescription(trans, role.ns, role.name, role.description);
-        if(rdr.isOK()) {
+        Result<Void> rdr = ques.roleDAO().addDescription(trans, role.ns, role.name, role.description);
+        if (rdr.isOK()) {
             return Result.ok();
         } else {
             return Result.err(rdr);
         }
 
     }
-    
+
     @ApiDoc(
             method = POST,
             path = "/authz/role/perm",
@@ -1829,7 +1918,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             expectedCode = 201,
             errorCodes = {403,404,406,409},
             text = { "Grant a Permission to a Role",
-                     "Permission consists of:", 
+                     "Permission consists of:",
                      "<ul><li>type - a Namespace qualified identifier specifying what kind of resource "
                      + "is being protected</li>",
                      "<li>instance - a key, possibly multi-dimensional, that identifies a specific "
@@ -1846,38 +1935,38 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> addPermToRole(final AuthzTrans trans, REQUEST rreq) {
         // Translate Request into Perm and Role Objects
         final Result<PermDAO.Data> rpd = mapper.permFromRPRequest(trans, rreq);
-        if(rpd.notOKorIsEmpty()) {
+        if (rpd.notOKorIsEmpty()) {
             return Result.err(rpd);
         }
         final Result<RoleDAO.Data> rrd = mapper.roleFromRPRequest(trans, rreq);
-        if(rrd.notOKorIsEmpty()) {
+        if (rrd.notOKorIsEmpty()) {
             return Result.err(rrd);
         }
-        
+
         // Validate Role and Perm values
         final ServiceValidator v = new ServiceValidator();
-        if(v.perm(rpd.value)
+        if (v.perm(rpd.value)
             .role(rrd.value)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
-        Result<List<RoleDAO.Data>> rlrd = ques.roleDAO.read(trans, rrd.value.ns, rrd.value.name);
-        if(rlrd.notOKorIsEmpty()) {
+        Result<List<RoleDAO.Data>> rlrd = ques.roleDAO().read(trans, rrd.value.ns, rrd.value.name);
+        if (rlrd.notOKorIsEmpty()) {
             return Result.err(Status.ERR_RoleNotFound, "Role [%s] does not exist", rrd.value.fullName());
         }
-        
+
         // Check Status of Data in DB (does it exist)
-        Result<List<PermDAO.Data>> rlpd = ques.permDAO.read(trans, rpd.value.ns, 
+        Result<List<PermDAO.Data>> rlpd = ques.permDAO().read(trans, rpd.value.ns,
                 rpd.value.type, rpd.value.instance, rpd.value.action);
         PermDAO.Data createPerm = null; // if not null, create first
-        if(rlpd.notOKorIsEmpty()) { // Permission doesn't exist
-            if(trans.requested(force)) {
+        if (rlpd.notOKorIsEmpty()) { // Permission doesn't exist
+            if (trans.requested(force)) {
                 // Remove roles from perm data object so we just create the perm here
                 createPerm = rpd.value;
                 createPerm.roles.clear();
             } else {
-                return Result.err(Status.ERR_PermissionNotFound,"Permission [%s.%s|%s|%s] does not exist", 
+                return Result.err(Status.ERR_PermissionNotFound,"Permission [%s.%s|%s|%s] does not exist",
                         rpd.value.ns,rpd.value.type,rpd.value.instance,rpd.value.action);
             }
         } else {
@@ -1890,7 +1979,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             }
         }
 
-        
+
         Result<FutureDAO.Data> fd = mapper.future(trans, PermDAO.TABLE, rreq, rpd.value,true, // Allow grants to create Approvals
                 new Mapper.Memo() {
                     @Override
@@ -1903,45 +1992,48 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     private Result<NsDAO.Data> nsd;
                     @Override
                     public Result<?> mayChange() {
-                        if(nsd==null) {
+                        if (nsd==null) {
                             nsd = ques.mayUser(trans, trans.user(), rpd.value, Access.write);
+                            if(nsd.notOK()) {
+                                trans.requested(REQD_TYPE.future,true);
+                            }
                         }
                         return nsd;
                     }
                 });
-        Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, rpd.value.ns);
-        if(nsr.notOKorIsEmpty()) {
+        Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, rpd.value.ns);
+        if (nsr.notOKorIsEmpty()) {
             return Result.err(nsr);
         }
         switch(fd.status) {
-        case OK:
-            Result<String> rfc = func.createFuture(trans,fd.value, 
-                    rpd.value.fullPerm(),
-                    trans.user(),
-                    nsr.value.get(0),
-                    FUTURE_OP.G);
-            if(rfc.isOK()) {
-                return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing",
-                        rpd.value.ns,
-                        rpd.value.type,
-                        rpd.value.instance,
-                        rpd.value.action);
-            } else { 
-                return Result.err(rfc);
-            }
-        case Status.ACC_Now:
-            Result<Void> rv = null;
-            if(createPerm!=null) {// has been validated for creating
-                rv = func.createPerm(trans, createPerm, false);
-            }
-            if(rv==null || rv.isOK()) {
-                rv = func.addPermToRole(trans, rrd.value, rpd.value, false);
-            }
-            return rv;
-        default:
-            return Result.err(fd);
+            case OK:
+                Result<String> rfc = func.createFuture(trans,fd.value,
+                        rpd.value.fullPerm(),
+                        trans.user(),
+                        nsr.value.get(0),
+                        FUTURE_OP.G);
+                if (rfc.isOK()) {
+                    return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing",
+                            rpd.value.ns,
+                            rpd.value.type,
+                            rpd.value.instance,
+                            rpd.value.action);
+                } else {
+                    return Result.err(rfc);
+                }
+            case Status.ACC_Now:
+                Result<Void> rv = null;
+                if (createPerm!=null) {// has been validated for creating
+                    rv = func.createPerm(trans, createPerm, false);
+                }
+                if (rv==null || rv.isOK()) {
+                    rv = func.addPermToRole(trans, rrd.value, rpd.value, false);
+                }
+                return rv;
+            default:
+                return Result.err(fd);
         }
-        
+
     }
 
     /**
@@ -1962,16 +2054,16 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<Void> delPermFromRole(final AuthzTrans trans, REQUEST rreq) {
         final Result<PermDAO.Data> updt = mapper.permFromRPRequest(trans, rreq);
-        if(updt.notOKorIsEmpty()) {
+        if (updt.notOKorIsEmpty()) {
             return Result.err(updt);
         }
         final Result<RoleDAO.Data> rrd = mapper.roleFromRPRequest(trans, rreq);
-        if(rrd.notOKorIsEmpty()) {
+        if (rrd.notOKorIsEmpty()) {
             return Result.err(rrd);
         }
 
         final ServiceValidator v = new ServiceValidator();
-        if(v.nullOrBlank(updt.value)
+        if (v.nullOrBlank(updt.value)
             .nullOrBlank(rrd.value)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
@@ -1979,17 +2071,17 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
 
         return delPermFromRole(trans, updt.value,rrd.value, rreq);
     }
-        
-    private Result<Void> delPermFromRole(final AuthzTrans trans, PermDAO.Data pdd, RoleDAO.Data rdd, REQUEST rreq) {        
-        Result<List<PermDAO.Data>> rlpd = ques.permDAO.read(trans, pdd.ns, pdd.type, 
+
+    private Result<Void> delPermFromRole(final AuthzTrans trans, PermDAO.Data pdd, RoleDAO.Data rdd, REQUEST rreq) {
+        Result<List<PermDAO.Data>> rlpd = ques.permDAO().read(trans, pdd.ns, pdd.type,
                 pdd.instance, pdd.action);
-        
-        if(rlpd.notOKorIsEmpty()) {
-            return Result.err(Status.ERR_PermissionNotFound, 
+
+        if (rlpd.notOKorIsEmpty()) {
+            return Result.err(Status.ERR_PermissionNotFound,
                 "Permission [%s.%s|%s|%s] does not exist",
                     pdd.ns,pdd.type,pdd.instance,pdd.action);
         }
-        
+
         Result<FutureDAO.Data> fd = mapper.future(trans, PermDAO.TABLE, rreq, pdd,true, // allow ungrants requests
                 new Mapper.Memo() {
                     @Override
@@ -2002,25 +2094,25 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     private Result<NsDAO.Data> nsd;
                     @Override
                     public Result<?> mayChange() {
-                        if(nsd==null) {
+                        if (nsd==null) {
                             nsd = ques.mayUser(trans, trans.user(), pdd, Access.write);
                         }
                         return nsd;
                     }
                 });
-        Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, pdd.ns);
-        if(nsr.notOKorIsEmpty()) {
+        Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, pdd.ns);
+        if (nsr.notOKorIsEmpty()) {
             return Result.err(nsr);
         }
         switch(fd.status) {
             case OK:
-                Result<String> rfc = func.createFuture(trans,fd.value, 
+                Result<String> rfc = func.createFuture(trans,fd.value,
                         pdd.fullPerm(),
                         trans.user(),
                         nsr.value.get(0),
                         FUTURE_OP.UG
                         );
-                if(rfc.isOK()) {
+                if (rfc.isOK()) {
                     return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing",
                             pdd.ns,
                             pdd.type,
@@ -2035,7 +2127,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                 return Result.err(fd);
         }
     }
-    
+
 /*
     @ApiDoc(
             method = DELETE,
@@ -2053,38 +2145,38 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<Void> delPermFromRole(AuthzTrans trans, String role, String type, String instance, String action) {
         Result<Data> rpns = ques.deriveNs(trans, type);
-        if(rpns.notOKorIsEmpty()) {
+        if (rpns.notOKorIsEmpty()) {
             return Result.err(rpns);
         }
-        
+
             final Validator v = new ServiceValidator();
-        if(v.role(role)
+        if (v.role(role)
             .permType(rpns.value.name,rpns.value.parent)
             .permInstance(instance)
             .permAction(action)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
             Result<Data> rrns = ques.deriveNs(trans, role);
-            if(rrns.notOKorIsEmpty()) {
+            if (rrns.notOKorIsEmpty()) {
                 return Result.err(rrns);
             }
-            
-        final Result<List<RoleDAO.Data>> rrd = ques.roleDAO.read(trans, rrns.value.parent, rrns.value.name);
-        if(rrd.notOKorIsEmpty()) {
+
+        final Result<List<RoleDAO.Data>> rrd = ques.roleDAO().read(trans, rrns.value.parent, rrns.value.name);
+        if (rrd.notOKorIsEmpty()) {
             return Result.err(rrd);
         }
-        
-        final Result<List<PermDAO.Data>> rpd = ques.permDAO.read(trans, rpns.value.parent, rpns.value.name, instance, action);
-        if(rpd.notOKorIsEmpty()) {
+
+        final Result<List<PermDAO.Data>> rpd = ques.permDAO().read(trans, rpns.value.parent, rpns.value.name, instance, action);
+        if (rpd.notOKorIsEmpty()) {
             return Result.err(rpd);
         }
 
-        
+
         return delPermFromRole(trans,rpd.value.get(0), rrd.value.get(0), mapper.ungrantRequest(trans, role, type, instance, action));
     }
-    
+
     @ApiDoc(
             method = DELETE,
             path = "/authz/role/:role",
@@ -2097,9 +2189,9 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<Void> deleteRole(AuthzTrans trans, String role)  {
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans,ques,role);
-        if(rrdd.isOKhasData()) {
+        if (rrdd.isOKhasData()) {
             final ServiceValidator v = new ServiceValidator();
-            if(v.nullOrBlank(rrdd.value).err()) { 
+            if (v.nullOrBlank(rrdd.value).err()) {
                 return Result.err(Status.ERR_BadData,v.errs());
             }
             return func.deleteRole(trans, rrdd.value, false, false);
@@ -2125,50 +2217,45 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> deleteRole(final AuthzTrans trans, REQUEST from) {
         final Result<RoleDAO.Data> rd = mapper.role(trans, from);
         final ServiceValidator v = new ServiceValidator();
-        if(rd==null) {
+        if (rd==null) {
             return Result.err(Status.ERR_BadData,"Request does not contain Role");
         }
-        if(v.nullOrBlank(rd.value).err()) {
+        if (v.nullOrBlank(rd.value).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         final RoleDAO.Data role = rd.value;
-        if(ques.roleDAO.read(trans, role).notOKorIsEmpty() && !trans.requested(force)) {
+        if (ques.roleDAO().read(trans, role).notOKorIsEmpty() && !trans.requested(force)) {
             return Result.err(Status.ERR_RoleNotFound, "Role [" + role.fullName() + "] does not exist");
         }
 
         Result<FutureDAO.Data> fd = mapper.future(trans,RoleDAO.TABLE,from,role,false,
-                new Mapper.Memo() {
-                    @Override
-                    public String get() {
-                        return "Delete Role [" + role.fullName() + ']' 
-                                + " and all attached user roles";
-                    }
-                },
+            () -> "Delete Role [" + role.fullName() + ']'
+                    + " and all attached user roles",
             new MayChange() {
                 private Result<NsDAO.Data> nsd;
                 @Override
                 public Result<?> mayChange() {
-                    if(nsd==null) {
+                    if (nsd==null) {
                         nsd = ques.mayUser(trans, trans.user(), role, Access.write);
                     }
                     return nsd;
                 }
             });
-        
+
         switch(fd.status) {
         case OK:
-            Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, rd.value.ns);
-            if(nsr.notOKorIsEmpty()) {
+            Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, rd.value.ns);
+            if (nsr.notOKorIsEmpty()) {
                 return Result.err(nsr);
             }
-            
-            Result<String> rfc = func.createFuture(trans, fd.value, 
+
+            Result<String> rfc = func.createFuture(trans, fd.value,
                     role.encode(), trans.user(),nsr.value.get(0),FUTURE_OP.D);
-            if(rfc.isOK()) {
+            if (rfc.isOK()) {
                 return Result.err(Status.ACC_Future, "Role Deletion [%s.%s] is saved for future processing",
                         rd.value.ns,
                         rd.value.name);
-            } else { 
+            } else {
                 return Result.err(rfc);
             }
         case Status.ACC_Now:
@@ -2180,14 +2267,14 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
 /***********************************
- * CRED 
+ * CRED
  ***********************************/
     private class MayCreateCred implements MayChange {
         private Result<NsDAO.Data> nsd;
         private AuthzTrans trans;
         private CredDAO.Data cred;
         private Executor exec;
-        
+
         public MayCreateCred(AuthzTrans trans, CredDAO.Data cred, Executor exec) {
             this.trans = trans;
             this.cred = cred;
@@ -2196,18 +2283,18 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
 
         @Override
         public Result<?> mayChange() {
-            if(nsd==null) {
+            if (nsd==null) {
                 nsd = ques.validNSOfDomain(trans, cred.id);
             }
             // is Ns of CredID valid?
-            if(nsd.isOK()) {
+            if (nsd.isOK()) {
                 try {
                     // Check Org Policy
-                    if(trans.org().validate(trans,Policy.CREATE_MECHID, exec, cred.id)==null) {
-                        return Result.ok(); 
+                    if (trans.org().validate(trans,Policy.CREATE_MECHID, exec, cred.id)==null) {
+                        return Result.ok();
                     } else {
                        Result<?> rmc = ques.mayUser(trans, trans.user(), nsd.value, Access.write);
-                       if(rmc.isOKhasData()) {
+                       if (rmc.isOKhasData()) {
                            return rmc;
                        }
                     }
@@ -2222,50 +2309,70 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     }
 
     private class MayChangeCred implements MayChange {
-        
+        private static final String EXTEND = "extend";
+        private static final String RESET = "reset";
+        private static final String DELETE = "delete";
         private Result<NsDAO.Data> nsd;
         private AuthzTrans trans;
         private CredDAO.Data cred;
-        public MayChangeCred(AuthzTrans trans, CredDAO.Data cred) {
+        private String action;
+        public MayChangeCred(AuthzTrans trans, CredDAO.Data cred, String action) {
             this.trans = trans;
             this.cred = cred;
+            this.action = action;
         }
 
         @Override
         public Result<?> mayChange() {
             // User can change himself (but not create)
-            if(trans.user().equals(cred.id)) {
-                return Result.ok();
-            }
-            if(nsd==null) {
+            if (nsd==null) {
                 nsd = ques.validNSOfDomain(trans, cred.id);
             }
             // Get the Namespace
-            if(nsd.isOK()) {
-                if(ques.mayUser(trans, trans.user(), nsd.value,Access.write).isOK()) {
-                    return Result.ok();
+            if (nsd.isOK()) {
+                String ns = nsd.value.name;
+                String user = trans.user();
+                String company;
+                String temp[] = Split.split('.',ns);
+                switch(temp.length) {
+                    case 0:
+                        company = Defaults.AAF_NS;
+                        break;
+                    case 1:
+                        company = temp[0];
+                        break;
+                    default:
+                        company = temp[0] + '.' + temp[1];
                 }
-                String user[] = Split.split('.',trans.user());
-                if(user.length>2) {
-                    String company = user[user.length-1] + '.' + user[user.length-2];
-                    if(ques.isGranted(trans, trans.user(), ROOT_NS,"password",company,"reset")) {
-                        return Result.ok();
-                    }
+                switch(action) {
+                    case DELETE:
+                       String why;
+                        if(ques.isOwner(trans, user,ns) ||
+                                       ques.isAdmin(trans, user,ns) ||
+                                       ques.isGranted(trans, user, ROOT_NS,"password",company,DELETE)) {
+                               return Result.ok();
+                        }
+                        break;
+                    case RESET:
+                    case EXTEND:
+                        if (ques.isGranted(trans, trans.user(), ROOT_NS,"password",company,action)) {
+                            return Result.ok();
+                        }
+                        break;
                 }
             }
-            return Result.err(Status.ERR_Denied,"%s is not allowed to change %s in %s",trans.user(),cred.id,cred.ns);
+            return Result.err(Status.ERR_Denied,"%s is not allowed to %s %s in %s",trans.user(),action,cred.id,cred.ns);
         }
-
     }
 
     private final long DAY_IN_MILLIS = 24*3600*1000L;
-    
-    @ApiDoc( 
-            method = POST,  
+
+    @ApiDoc(
+            method = POST,
             path = "/authn/cred",
             params = {},
             expectedCode = 201,
-            errorCodes = {403,404,406,409}, 
+            errorCodes = {403,404,406,409},
             text = { "A credential consists of:",
                      "<ul><li>id - the ID to create within AAF. The domain is in reverse",
                      "order of Namespace (i.e. Users of Namespace com.att.myapp would be",
@@ -2279,19 +2386,18 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> createUserCred(final AuthzTrans trans, REQUEST from) {
         final String cmdDescription = ("Create User Credential");
         TimeTaken tt = trans.start(cmdDescription, Env.SUB);
-        
+
         try {
             Result<CredDAO.Data> rcred = mapper.cred(trans, from, true);
-            if(rcred.isOKhasData()) {
-                byte[] rawCred = rcred.value.cred.array();
+            if (rcred.isOKhasData()) {
                 rcred = ques.userCredSetup(trans, rcred.value);
-                
+
                 final ServiceValidator v = new ServiceValidator();
-                
-                if(v.cred(trans, trans.org(),rcred,true).err()) { // Note: Creates have stricter Validations 
+
+                if (v.cred(trans, trans.org(),rcred,true).err()) { // Note: Creates have stricter Validations
                     return Result.err(Status.ERR_BadData,v.errs());
                 }
-                
+
 
                 // 2016-4 Jonathan, New Behavior - If MechID is not registered with Org, deny creation
                 Identity mechID =  null;
@@ -2301,21 +2407,21 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                 } catch (Exception e1) {
                     trans.error().log(e1,rcred.value.id,"cannot be validated at this time");
                 }
-                if(mechID==null || !mechID.isFound()) { 
+                if (mechID==null || !mechID.isFound()) {
                     return Result.err(Status.ERR_Policy,"MechIDs must be registered with %s before provisioning in AAF",org.getName());
                 }
 
-                Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, rcred.value.ns);
-                if(nsr.notOKorIsEmpty()) {
+                Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, rcred.value.ns);
+                if (nsr.notOKorIsEmpty()) {
                     return Result.err(Status.ERR_NsNotFound,"Cannot provision %s on non-existent Namespace %s",mechID.id(),rcred.value.ns);
                 }
-                
+
 
                 boolean firstID = false;
                 MayChange mc;
-                
+
                 CassExecutor exec = new CassExecutor(trans, func);
-                Result<List<CredDAO.Data>> rlcd = ques.credDAO.readID(trans, rcred.value.id);
+                Result<List<CredDAO.Data>> rlcd = ques.credDAO().readID(trans, rcred.value.id);
                 if (rlcd.isOKhasData()) {
                     if (!org.canHaveMultipleCreds(rcred.value.id)) {
                         return Result.err(Status.ERR_ConflictAlreadyExists, "Credential exists");
@@ -2325,84 +2431,109 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                         // May not use the same password in the list
                         // Note: ASPR specifies character differences, but we don't actually store the
                         // password to validate char differences.
-                        
-                        rb = ques.userCredCheck(trans, curr, rawCred);
-                        if(rb.notOK()) {
-                            return Result.err(rb);
-                        } else if(rb.value){
-                            return Result.err(Status.ERR_Policy, "Credential content cannot be reused.");
-                        } else if (Chrono.dateOnlyStamp(curr.expires).equals(Chrono.dateOnlyStamp(rcred.value.expires)) && curr.type==rcred.value.type) {
-                            return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists, use 'reset'");
+
+//                      byte[] rawCred = rcred.value.type==CredDAO.RAW?null:;                            return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists");
+                        if(rcred.value.type==CredDAO.FQI ) {
+                            if(curr.type==CredDAO.FQI) {
+                                return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists");
+                            }
+                        } else {
+
+                            rb = ques.userCredCheck(trans, curr, rcred.value.cred!=null?rcred.value.cred.array():null);
+                            if (rb.notOK()) {
+                                return Result.err(rb);
+                            } else if (rb.value){
+                                return Result.err(Status.ERR_Policy, "Credential content cannot be reused.");
+                            } else if(Chrono.dateOnlyStamp(curr.expires).equals(Chrono.dateOnlyStamp(rcred.value.expires))
+                                    && curr.type==rcred.value.type
+                                    ) {
+                                // Allow if expiring differential is greater than 1 day (for TEMP)
+                                // Unless expiring in 1 day
+                                if(System.currentTimeMillis() - rcred.value.expires.getTime() > TimeUnit.DAYS.toMillis(1)) {
+                                    return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists");
+                                }
+                            }
                         }
-                    }    
+                    }
                 } else {
                     try {
                     // 2016-04-12 Jonathan If Caller is the Sponsor and is also an Owner of NS, allow without special Perm
                         String theMechID = rcred.value.id;
                         Boolean otherMechIDs = false;
                         // find out if this is the only mechID.  other MechIDs mean special handling (not automated)
-                        for(CredDAO.Data cd : ques.credDAO.readNS(trans,nsr.value.get(0).name).value) {
-                            if(!cd.id.equals(theMechID)) {
+                        for (CredDAO.Data cd : ques.credDAO().readNS(trans,nsr.value.get(0).name).value) {
+                            if (!cd.id.equals(theMechID)) {
                                 otherMechIDs = true;
                                 break;
                             }
                         }
                         String reason;
                         // We can say "ID does not exist" here
-                        if((reason=org.validate(trans, Policy.CREATE_MECHID, exec, theMechID,trans.user(),otherMechIDs.toString()))!=null) {
-                            return Result.err(Status.ERR_Denied, reason); 
+                        if ((reason=org.validate(trans, Policy.CREATE_MECHID, exec, theMechID,trans.user(),otherMechIDs.toString()))!=null) {
+                            return Result.err(Status.ERR_Denied, reason);
                         }
                         firstID=true;
                     } catch (Exception e) {
                         return Result.err(e);
                     }
                 }
-    
+
                 mc = new MayCreateCred(trans, rcred.value, exec);
-                
+
                 final CredDAO.Data cdd = rcred.value;
                 Result<FutureDAO.Data> fd = mapper.future(trans,CredDAO.TABLE,from, rcred.value,false, // may want to enable in future.
                     new Mapper.Memo() {
                         @Override
                         public String get() {
-                            return cmdDescription + " [" + 
-                                cdd.id + '|' 
-                                + cdd.type + '|' 
+                            return cmdDescription + " [" +
+                                cdd.id + '|'
+                                + cdd.type + '|'
                                 + cdd.expires + ']';
                         }
                     },
                     mc);
-                
+
                 switch(fd.status) {
                     case OK:
-                        Result<String> rfc = func.createFuture(trans, fd.value, 
+                        Result<String> rfc = func.createFuture(trans, fd.value,
                                 rcred.value.id + '|' + rcred.value.type.toString() + '|' + rcred.value.expires,
                                 trans.user(), nsr.value.get(0), FUTURE_OP.C);
-                        if(rfc.isOK()) {
+                        if (rfc.isOK()) {
                             return Result.err(Status.ACC_Future, "Credential Request [%s|%s|%s] is saved for future processing",
                                     rcred.value.id,
                                     Integer.toString(rcred.value.type),
                                     rcred.value.expires.toString());
-                        } else { 
+                        } else {
                             return Result.err(rfc);
                         }
                     case Status.ACC_Now:
                         try {
-                            if(firstID) {
-    //                            && !nsr.value.get(0).isAdmin(trans.getUserPrincipal().getName())) {
-                                Result<List<String>> admins = func.getAdmins(trans, nsr.value.get(0).name, false);
-                                // OK, it's a first ID, and not by NS Admin, so let's set TempPassword length
-                                // Note, we only do this on First time, because of possibility of 
-                                // prematurely expiring a production id
-                                if(admins.isOKhasData() && !admins.value.contains(trans.user())) {
-                                    rcred.value.expires = org.expiration(null, Expiration.TempPassword).getTime();
+                            if (firstID) {
+                                // OK, it's a first ID, and not by NS Owner
+                               String user = trans.user();
+                                if(!ques.isOwner(trans,user,cdd.ns)) {
+                                    // Admins are not allowed to set first Cred, but Org has already
+                                    // said entity MAY create, typically by Permission
+                                    // We can't know which reason they are allowed here, so we
+                                    // have to assume that any with Special Permission would not be
+                                    // an Admin.
+                                       String domain = org.supportedDomain(user);
+                                    if((domain!=null && !ques.isGranted(trans, user, ROOT_NS, "mechid", domain, Question.CREATE)) &&
+                                               ques.isAdmin(trans, user, cdd.ns)) {
+                                        return Result.err(Result.ERR_Denied,
+                                            "Only Owners may create first passwords in their Namespace. Admins may modify after one exists" );
+                                    } else {
+                                        // Allow IDs that AREN'T part of NS with Org Onboarding Permission  (see Org object) to create Temp Passwords.
+                                        rcred.value.expires = org.expiration(null, Expiration.TempPassword).getTime();
+                                    }
                                 }
                             }
                         } catch (Exception e) {
                             trans.error().log(e, "While setting expiration to TempPassword");
                         }
-                        Result<?>udr = ques.credDAO.create(trans, rcred.value);
-                        if(udr.isOK()) {
+
+                        Result<?>udr = ques.credDAO().create(trans, rcred.value);
+                        if (udr.isOK()) {
                             return Result.ok();
                         }
                         return Result.err(udr);
@@ -2418,57 +2549,57 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         }
     }
 
-    @ApiDoc(   
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authn/creds/ns/:ns",
             params = {"ns|string|true"},
             expectedCode = 200,
-            errorCodes = {403,404,406}, 
+            errorCodes = {403,404,406},
             text = { "Return all IDs in Namespace :ns"
                      }
             )
     @Override
     public Result<USERS> getCredsByNS(AuthzTrans trans, String ns) {
         final Validator v = new ServiceValidator();
-        if(v.ns(ns).err()) {
+        if (v.ns(ns).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         // check if user is allowed to view NS
         Result<NsDAO.Data> rnd = ques.deriveNs(trans,ns);
-        if(rnd.notOK()) {
-            return Result.err(rnd); 
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
         rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
-        if(rnd.notOK()) {
-            return Result.err(rnd); 
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
-    
+
         TimeTaken tt = trans.start("MAP Creds by NS to Creds", Env.SUB);
-        try {            
+        try {
             USERS users = mapper.newInstance(API.USERS);
-            Result<List<CredDAO.Data>> rlcd = ques.credDAO.readNS(trans, ns);
-                    
-            if(rlcd.isOK()) {
-                if(!rlcd.isEmpty()) {
+            Result<List<CredDAO.Data>> rlcd = ques.credDAO().readNS(trans, ns);
+
+            if (rlcd.isOK()) {
+                if (!rlcd.isEmpty()) {
                     return mapper.cred(rlcd.value, users);
                 }
-                return Result.ok(users);        
+                return Result.ok(users);
             } else {
                 return Result.err(rlcd);
             }
         } finally {
             tt.done();
         }
-            
+
     }
 
-    @ApiDoc(   
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authn/creds/id/:ns",
             params = {"id|string|true"},
             expectedCode = 200,
-            errorCodes = {403,404,406}, 
+            errorCodes = {403,404,406},
             text = { "Return all IDs in for ID"
                     ,"(because IDs are multiple, due to multiple Expiration Dates)"
                      }
@@ -2476,62 +2607,62 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<USERS> getCredsByID(AuthzTrans trans, String id) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("ID",id).err()) {
+        if (v.nullOrBlank("ID",id).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         String ns = Question.domain2ns(id);
         // check if user is allowed to view NS
         Result<NsDAO.Data> rnd = ques.deriveNs(trans,ns);
-        if(rnd.notOK()) {
-            return Result.err(rnd); 
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
         rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
-        if(rnd.notOK()) {
-            return Result.err(rnd); 
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
-    
+
         TimeTaken tt = trans.start("MAP Creds by ID to Creds", Env.SUB);
-        try {            
+        try {
             USERS users = mapper.newInstance(API.USERS);
-            Result<List<CredDAO.Data>> rlcd = ques.credDAO.readID(trans, id);
-                    
-            if(rlcd.isOK()) {
-                if(!rlcd.isEmpty()) {
+            Result<List<CredDAO.Data>> rlcd = ques.credDAO().readID(trans, id);
+
+            if (rlcd.isOK()) {
+                if (!rlcd.isEmpty()) {
                     return mapper.cred(rlcd.value, users);
                 }
-                return Result.ok(users);        
+                return Result.ok(users);
             } else {
                 return Result.err(rlcd);
             }
         } finally {
             tt.done();
         }
-            
+
     }
 
-    @ApiDoc(   
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authn/certs/id/:id",
             params = {"id|string|true"},
             expectedCode = 200,
-            errorCodes = {403,404,406}, 
+            errorCodes = {403,404,406},
             text = { "Return Cert Info for ID"
                    }
             )
     @Override
     public Result<CERTS> getCertInfoByID(AuthzTrans trans, HttpServletRequest req, String id) {
         TimeTaken tt = trans.start("Get Cert Info by ID", Env.SUB);
-        try {            
+        try {
             CERTS certs = mapper.newInstance(API.CERTS);
-            Result<List<CertDAO.Data>> rlcd = ques.certDAO.readID(trans, id);
-                    
-            if(rlcd.isOK()) {
-                if(!rlcd.isEmpty()) {
+            Result<List<CertDAO.Data>> rlcd = ques.certDAO().readID(trans, id);
+
+            if (rlcd.isOK()) {
+                if (!rlcd.isEmpty()) {
                     return mapper.cert(rlcd.value, certs);
                 }
-                return Result.ok(certs);        
-            } else { 
+                return Result.ok(certs);
+            } else {
                 return Result.err(rlcd);
             }
         } finally {
@@ -2540,79 +2671,81 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
 
     }
 
-    @ApiDoc( 
-            method = PUT,  
+    @ApiDoc(
+            method = PUT,
             path = "/authn/cred",
             params = {},
             expectedCode = 200,
-            errorCodes = {300,403,404,406}, 
+            errorCodes = {300,403,404,406},
             text = { "Reset a Credential Password. If multiple credentials exist for this",
                         "ID, you will need to specify which entry you are resetting in the",
                         "CredRequest object"
                      }
             )
     @Override
-    public Result<Void> changeUserCred(final AuthzTrans trans, REQUEST from) {
+    public Result<Void> resetUserCred(final AuthzTrans trans, REQUEST from) {
         final String cmdDescription = "Update User Credential";
         TimeTaken tt = trans.start(cmdDescription, Env.SUB);
         try {
             Result<CredDAO.Data> rcred = mapper.cred(trans, from, true);
-            if(rcred.isOKhasData()) {
+            if (rcred.isOKhasData()) {
                 rcred = ques.userCredSetup(trans, rcred.value);
-    
+
                 final ServiceValidator v = new ServiceValidator();
-                
-                if(v.cred(trans, trans.org(),rcred,false).err()) {// Note: Creates have stricter Validations 
+
+                if (v.cred(trans, trans.org(),rcred,false).err()) {// Note: Creates have stricter Validations
                     return Result.err(Status.ERR_BadData,v.errs());
                 }
-                Result<List<CredDAO.Data>> rlcd = ques.credDAO.readID(trans, rcred.value.id);
-                if(rlcd.notOKorIsEmpty()) {
+                Result<List<CredDAO.Data>> rlcd = ques.credDAO().readID(trans, rcred.value.id);
+                if (rlcd.notOKorIsEmpty()) {
                     return Result.err(Status.ERR_UserNotFound, "Credential does not exist");
-                } 
-                
-                MayChange mc = new MayChangeCred(trans, rcred.value);
-                Result<?> rmc = mc.mayChange(); 
+                }
+
+                MayChange mc = new MayChangeCred(trans, rcred.value,MayChangeCred.RESET);
+                Result<?> rmc = mc.mayChange();
                 if (rmc.notOK()) {
                     return Result.err(rmc);
                 }
-                
-                 Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, rlcd.value);
-                if(ri.notOK()) {
+
+                List<CredDAO.Data> lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256);
+
+                Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, lcdd, MayChangeCred.RESET);
+                if (ri.notOK()) {
                     return Result.err(ri);
                 }
                 int entry = ri.value;
-    
-                
+
+
                 final CredDAO.Data cred = rcred.value;
-                
+
                 Result<FutureDAO.Data> fd = mapper.future(trans,CredDAO.TABLE,from, rcred.value,false,
                 new Mapper.Memo() {
                     @Override
                     public String get() {
-                        return cmdDescription + " [" + 
-                            cred.id + '|' 
-                            + cred.type + '|' 
+                        return cmdDescription + " [" +
+                            cred.id + '|'
+                            + cred.type + '|'
                             + cred.expires + ']';
                     }
                 },
                 mc);
-                
-                Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, rcred.value.ns);
-                if(nsr.notOKorIsEmpty()) {
+
+                Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, rcred.value.ns);
+                if (nsr.notOKorIsEmpty()) {
                     return Result.err(nsr);
                 }
-    
+
                 switch(fd.status) {
                     case OK:
-                        Result<String> rfc = func.createFuture(trans, fd.value, 
+                        Result<String> rfc = func.createFuture(trans, fd.value,
                                 rcred.value.id + '|' + rcred.value.type.toString() + '|' + rcred.value.expires,
                                 trans.user(), nsr.value.get(0), FUTURE_OP.U);
-                        if(rfc.isOK()) {
+                        if (rfc.isOK()) {
                             return Result.err(Status.ACC_Future, "Credential Request [%s|%s|%s]",
                                     rcred.value.id,
                                     Integer.toString(rcred.value.type),
                                     rcred.value.expires.toString());
-                        } else { 
+                        } else {
                             return Result.err(rfc);
                         }
                     case Status.ACC_Now:
@@ -2620,35 +2753,33 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                         // If we are Resetting Password on behalf of someone else (am not the Admin)
                         //  use TempPassword Expiration time.
                         Expiration exp;
-                        if(ques.isAdmin(trans, trans.user(), nsr.value.get(0).name)) {
+                        if (ques.isAdmin(trans, trans.user(), nsr.value.get(0).name)) {
                             exp = Expiration.Password;
                         } else {
                             exp = Expiration.TempPassword;
                         }
-                        
+
                         Organization org = trans.org();
                         CredDAO.Data current = rlcd.value.get(entry);
                         // If user resets password in same day, we will have a primary key conflict, so subtract 1 day
-                        if (current.expires.equals(rcred.value.expires) 
+                        if (current.expires.equals(rcred.value.expires)
                                     && rlcd.value.get(entry).type==rcred.value.type) {
                             GregorianCalendar gc = org.expiration(null, exp,rcred.value.id);
                             gc = Chrono.firstMomentOfDay(gc);
-                            gc.set(GregorianCalendar.HOUR_OF_DAY, org.startOfDay());                        
+                            gc.set(GregorianCalendar.HOUR_OF_DAY, org.startOfDay());
                             rcred.value.expires = new Date(gc.getTimeInMillis() - DAY_IN_MILLIS);
                         } else {
                             rcred.value.expires = org.expiration(null,exp).getTime();
                         }
-                        // Copy in other fields 10/21/2016
-                        rcred.value.notes=current.notes;
 
-                        udr = ques.credDAO.create(trans, rcred.value);
-                        if(udr.isOK()) {
-                            udr = ques.credDAO.delete(trans, rlcd.value.get(entry),false);
+                        udr = ques.credDAO().create(trans, rcred.value);
+                        if (udr.isOK()) {
+                            udr = ques.credDAO().delete(trans, rlcd.value.get(entry),false);
                         }
                         if (udr.isOK()) {
                             return Result.ok();
                         }
-    
+
                         return Result.err(udr);
                     default:
                         return Result.err(fd);
@@ -2661,33 +2792,12 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         }
     }
 
-    /*
-     * Codify the way to get Either Choice Needed or actual Integer from Credit Request
-     */
-    private Result<Integer> selectEntryIfMultiple(final CredRequest cr, List<CredDAO.Data> lcd) {
-        int entry = 0;
-        if (lcd.size() > 1) {
-            String inputOption = cr.getEntry();
-            if (inputOption == null) {
-                String message = selectCredFromList(lcd, false);
-                String[] variables = buildVariables(lcd);
-                return Result.err(Status.ERR_ChoiceNeeded, message, variables);
-            } else {
-                entry = Integer.parseInt(inputOption) - 1;
-            }
-            if (entry < 0 || entry >= lcd.size()) {
-                return Result.err(Status.ERR_BadData, "User chose invalid credential selection");
-            }
-        }
-        return Result.ok(entry);
-    }
-    
-    @ApiDoc( 
-            method = PUT,  
+    @ApiDoc(
+            method = PUT,
             path = "/authn/cred/:days",
             params = {"days|string|true"},
             expectedCode = 200,
-            errorCodes = {300,403,404,406}, 
+            errorCodes = {300,403,404,406},
             text = { "Extend a Credential Expiration Date. The intention of this API is",
                         "to avoid an outage in PROD due to a Credential expiring before it",
                         "can be configured correctly. Measures are being put in place ",
@@ -2701,12 +2811,12 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             Result<CredDAO.Data> cred = mapper.cred(trans, from, false);
             Organization org = trans.org();
             final ServiceValidator v = new ServiceValidator();
-            if(v.notOK(cred).err() || 
+            if (v.notOK(cred).err() ||
                v.nullOrBlank(cred.value.id, "Invalid ID").err() ||
                v.user(org,cred.value.id).err())  {
                  return Result.err(Status.ERR_BadData,v.errs());
             }
-            
+
             try {
                 String reason;
                 if ((reason=org.validate(trans, Policy.MAY_EXTEND_CRED_EXPIRES, new CassExecutor(trans,func)))!=null) {
@@ -2717,83 +2827,54 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                 trans.error().log(e, msg="Could not contact Organization for User Validation");
                 return Result.err(Status.ERR_Denied, msg);
             }
-    
+
             // Get the list of Cred Entries
-            Result<List<CredDAO.Data>> rlcd = ques.credDAO.readID(trans, cred.value.id);
-            if(rlcd.notOKorIsEmpty()) {
+            Result<List<CredDAO.Data>> rlcd = ques.credDAO().readID(trans, cred.value.id);
+            if (rlcd.notOKorIsEmpty()) {
                 return Result.err(Status.ERR_UserNotFound, "Credential does not exist");
             }
 
+            // Only Passwords can be extended
+            List<CredDAO.Data> lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256);
+
             //Need to do the "Pick Entry" mechanism
-            Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, rlcd.value);
-            if(ri.notOK()) {
+            // Note, this sorts
+            Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, lcdd, MayChangeCred.EXTEND);
+            if (ri.notOK()) {
                 return Result.err(ri);
             }
 
-            CredDAO.Data found = rlcd.value.get(ri.value);
+            CredDAO.Data found = lcdd.get(ri.value);
             CredDAO.Data cd = cred.value;
             // Copy over the cred
             cd.id = found.id;
             cd.cred = found.cred;
             cd.other = found.other;
             cd.type = found.type;
-            cd.notes = found.notes;
             cd.ns = found.ns;
+            cd.notes = "Extended";
+            cd.tag = found.tag;
             cd.expires = org.expiration(null, Expiration.ExtendPassword,days).getTime();
-            
-            cred = ques.credDAO.create(trans, cd);
-            if(cred.isOK()) {
+            if(cd.expires.before(found.expires)) {
+                return Result.err(Result.ERR_BadData,String.format("Credential's expiration date is more than %s days in the future",days));
+            }
+
+            cred = ques.credDAO().create(trans, cd);
+            if (cred.isOK()) {
                 return Result.ok();
             }
             return Result.err(cred);
         } finally {
             tt.done();
         }
-    }    
-
-    private String[] buildVariables(List<CredDAO.Data> value) {
-        // ensure credentials are sorted so we can fully automate Cred regression test
-        Collections.sort(value, new Comparator<CredDAO.Data>() {
-            @Override
-            public int compare(CredDAO.Data cred1, CredDAO.Data cred2) {
-                return cred1.expires.compareTo(cred2.expires);
-            }            
-        });
-        String [] vars = new String[value.size()+1];
-        vars[0]="Choice";
-        for (int i = 0; i < value.size(); i++) {
-        vars[i+1] = value.get(i).id + "    " + value.get(i).type 
-                + "    |" + value.get(i).expires;
-        }
-        return vars;
-    }
-    
-    private String selectCredFromList(List<CredDAO.Data> value, boolean isDelete) {
-        StringBuilder errMessage = new StringBuilder();
-        String userPrompt = isDelete?"Select which cred to delete (set force=true to delete all):":"Select which cred to update:";
-        int numSpaces = value.get(0).id.length() - "Id".length();
-        
-        errMessage.append(userPrompt + '\n');
-        errMessage.append("       Id");
-        for (int i = 0; i < numSpaces; i++) {
-            errMessage.append(' ');
-        }
-        errMessage.append("   Type  Expires" + '\n');
-        for(int i=0;i<value.size();++i) {
-            errMessage.append("    %s\n");
-        }
-        errMessage.append("Run same command again with chosen entry as last parameter");
-        
-        return errMessage.toString();
-        
     }
 
-    @ApiDoc( 
-            method = DELETE,  
+    @ApiDoc(
+            method = DELETE,
             path = "/authn/cred",
             params = {},
             expectedCode = 200,
-            errorCodes = {300,403,404,406}, 
+            errorCodes = {300,403,404,406},
             text = { "Delete a Credential. If multiple credentials exist for this",
                     "ID, you will need to specify which entry you are deleting in the",
                     "CredRequest object."
@@ -2803,117 +2884,148 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> deleteUserCred(AuthzTrans trans, REQUEST from)  {
         final Result<CredDAO.Data> cred = mapper.cred(trans, from, false);
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("cred", cred.value.id).err()) {
+        if (v.nullOrBlank("cred", cred.value.id).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-    
-        Result<List<CredDAO.Data>> rlcd = ques.credDAO.readID(trans, cred.value.id);
-        if(rlcd.notOKorIsEmpty()) {
-            // Empty Creds should have no user_roles.
-            Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByUser(trans, cred.value.id);
-            if(rlurd.isOK()) {
-                for(UserRoleDAO.Data data : rlurd.value) {
-                    ques.userRoleDAO.delete(trans, data, false);
+
+        MayChange mc = new MayChangeCred(trans,cred.value,MayChangeCred.DELETE);
+        Result<?> rmc = mc.mayChange();
+        if (rmc.notOK()) {
+            return Result.err(rmc);
+        }
+
+        boolean doForce = trans.requested(force);
+        Result<List<CredDAO.Data>> rlcd = ques.credDAO().readID(trans, cred.value.id);
+        if (rlcd.notOKorIsEmpty()) {
+            // Empty Creds should not have user_roles.
+            Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id);
+            if (rlurd.isOKhasData()) {
+                for (UserRoleDAO.Data data : rlurd.value) {
+                    ques.userRoleDAO().delete(trans, data, false);
                 }
             }
             return Result.err(Status.ERR_UserNotFound, "Credential does not exist");
         }
         boolean isLastCred = rlcd.value.size()==1;
-        
-        MayChange mc = new MayChangeCred(trans,cred.value);
-        Result<?> rmc = mc.mayChange(); 
-        if (rmc.notOK()) {
-            return Result.err(rmc);
-        }
-        
-        int entry = 0;
-        if(!trans.requested(force)) {
-            if (rlcd.value.size() > 1) {
-                CredRequest cr = (CredRequest)from;
-                String inputOption = cr.getEntry();
-                if (inputOption == null) {
-                    String message = selectCredFromList(rlcd.value, true);
-                    String[] variables = buildVariables(rlcd.value);
-                    return Result.err(Status.ERR_ChoiceNeeded, message, variables);
-                } else {
-                    try {
-                        if(inputOption.length()>5) { // should be a date
-                            Date d = Chrono.xmlDatatypeFactory.newXMLGregorianCalendar(inputOption).toGregorianCalendar().getTime();
-                            entry = 0;
-                            for(CredDAO.Data cd : rlcd.value) {
-                                if(cd.type.equals(cr.getType()) && cd.expires.equals(d)) {
-                                    break;
+
+        int entry;
+        CredRequest cr = (CredRequest)from;
+        if(isLastCred) {
+            if(cr.getEntry()==null || "1".equals(cr.getEntry())) {
+                entry = 0;
+            } else {
+                return Result.err(Status.ERR_BadData, "User chose invalid credential selection");
+            }
+        } else {
+            entry = -1;
+            int fentry = entry;
+            if(cred.value.type==CredDAO.FQI) {
+                entry = -1;
+                for(CredDAO.Data cdd : rlcd.value) {
+                    ++fentry;
+                    if(cdd.type == CredDAO.FQI) {
+                        entry = fentry;
+                        break;
+                    }
+                }
+            } else {
+                if (!doForce) {
+                    if (rlcd.value.size() > 1) {
+                        String inputOption = cr.getEntry();
+                        if (inputOption == null) {
+                            List<CredDAO.Data> list = filterList(rlcd.value,CredDAO.BASIC_AUTH,CredDAO.BASIC_AUTH_SHA256,CredDAO.CERT_SHA256_RSA);
+                            String message = selectCredFromList(list, MayChangeCred.DELETE);
+                            Object[] variables = buildVariables(list);
+                            return Result.err(Status.ERR_ChoiceNeeded, message, variables);
+                        } else {
+                            try {
+                                if (inputOption.length()>5) { // should be a date
+                                    Date d = Chrono.xmlDatatypeFactory.newXMLGregorianCalendar(inputOption).toGregorianCalendar().getTime();
+                                    for (CredDAO.Data cd : rlcd.value) {
+                                        ++fentry;
+                                        if (cd.type.equals(cr.getType()) && cd.expires.equals(d)) {
+                                            entry = fentry;
+                                            break;
+                                        }
+                                    }
+                                } else {
+                                    entry = Integer.parseInt(inputOption) - 1;
+                                    int count = 0;
+                                    for (CredDAO.Data cd : rlcd.value) {
+                                        if(cd.type!=CredDAO.BASIC_AUTH && cd.type!=CredDAO.BASIC_AUTH_SHA256 && cd.type!=CredDAO.CERT_SHA256_RSA) {
+                                            ++entry;
+                                        }
+                                        if(++count>entry) {
+                                            break;
+                                        }
+                                    }
                                 }
-                                ++entry;
+                            } catch (NullPointerException e) {
+                                return Result.err(Status.ERR_BadData, "Invalid Date Format for Entry");
+                            } catch (NumberFormatException e) {
+                                return Result.err(Status.ERR_BadData, "User chose invalid credential selection");
                             }
-                        } else {
-                            entry = Integer.parseInt(inputOption) - 1;
                         }
-                    } catch(NullPointerException e) {
-                        return Result.err(Status.ERR_BadData, "Invalid Date Format for Entry");
-                    } catch(NumberFormatException e) {
+                        isLastCred = (entry==-1);
+                    } else {
+                        isLastCred = true;
+                    }
+                    if (entry < -1 || entry >= rlcd.value.size()) {
                         return Result.err(Status.ERR_BadData, "User chose invalid credential selection");
                     }
                 }
-                isLastCred = (entry==-1)?true:false;
-            } else {
-                isLastCred = true;
-            }
-            if (entry < -1 || entry >= rlcd.value.size()) {
-                return Result.err(Status.ERR_BadData, "User chose invalid credential selection");
             }
         }
-        
-        Result<FutureDAO.Data> fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false, 
-            new Mapper.Memo() {
-                @Override
-                public String get() {
-                    return "Delete Credential [" + 
-                        cred.value.id + 
-                        ']';
-                }
-            },
+
+        Result<FutureDAO.Data> fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false,
+            () -> "Delete Credential [" +
+                cred.value.id +
+                ']',
             mc);
-    
-        Result<List<NsDAO.Data>> nsr = ques.nsDAO.read(trans, cred.value.ns);
-        if(nsr.notOKorIsEmpty()) {
+
+        Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, cred.value.ns);
+        if (nsr.notOKorIsEmpty()) {
             return Result.err(nsr);
         }
-    
+
         switch(fd.status) {
             case OK:
                 Result<String> rfc = func.createFuture(trans, fd.value, cred.value.id,
                         trans.user(), nsr.value.get(0), FUTURE_OP.D);
-    
-                if(rfc.isOK()) {
+
+                if (rfc.isOK()) {
                     return Result.err(Status.ACC_Future, "Credential Delete [%s] is saved for future processing",cred.value.id);
-                } else { 
+                } else {
                     return Result.err(rfc);
                 }
             case Status.ACC_Now:
                 Result<?>udr = null;
                 if (!trans.requested(force)) {
-                    if(entry<0 || entry >= rlcd.value.size()) {
-                        return Result.err(Status.ERR_BadData,"Invalid Choice [" + entry + "] chosen for Delete [%s] is saved for future processing",cred.value.id);
+                    if (entry<0 || entry >= rlcd.value.size()) {
+                        if(cred.value.type==CredDAO.FQI) {
+                            return Result.err(Status.ERR_BadData,"FQI does not exist");
+                        } else {
+                            return Result.err(Status.ERR_BadData,"Invalid Choice [" + entry + "] chosen for Delete [%s] is saved for future processing",cred.value.id);
+                        }
                     }
-                    udr = ques.credDAO.delete(trans, rlcd.value.get(entry),false);
+                    udr = ques.credDAO().delete(trans, rlcd.value.get(entry),false);
                 } else {
                     for (CredDAO.Data curr : rlcd.value) {
-                        udr = ques.credDAO.delete(trans, curr, false);
+                        udr = ques.credDAO().delete(trans, curr, false);
                         if (udr.notOK()) {
                             return Result.err(udr);
                         }
                     }
                 }
-                if(isLastCred) {
-                    Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByUser(trans, cred.value.id);
-                    if(rlurd.isOK()) {
-                        for(UserRoleDAO.Data data : rlurd.value) {
-                            ques.userRoleDAO.delete(trans, data, false);
+                if (isLastCred) {
+                    Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id);
+                    if (rlurd.isOK()) {
+                        for (UserRoleDAO.Data data : rlurd.value) {
+                            ques.userRoleDAO().delete(trans, data, false);
                         }
                     }
                 }
-                if(udr==null) {
+                if (udr==null) {
                     return Result.err(Result.ERR_NotFound,"No User Data found");
                 }
                 if (udr.isOK()) {
@@ -2923,9 +3035,112 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             default:
                 return Result.err(fd);
         }
-    
+
+    }
+
+    /*
+     * Codify the way to get Either Choice Needed or actual Integer from Credit Request
+     */
+    private Result<Integer> selectEntryIfMultiple(final CredRequest cr, List<CredDAO.Data> lcd, String action) {
+        int entry = 0;
+        if (lcd.size() > 1) {
+            String inputOption = cr.getEntry();
+            if (inputOption == null) {
+                String message = selectCredFromList(lcd, action);
+                Object[] variables = buildVariables(lcd);
+                return Result.err(Status.ERR_ChoiceNeeded, message, variables);
+            } else {
+                if(MayChangeCred.EXTEND.equals(action)) {
+                    // might be Tag
+                    if(inputOption.length()>4) { //Tag is at least 12
+                        int e = 0;
+                        CredDAO.Data last = null;
+                        int lastIdx = -1;
+                        for(CredDAO.Data cdd : lcd) {
+                            if(inputOption.equals(cdd.tag)) {
+                                if(last==null) {
+                                    last = cdd;
+                                    lastIdx = e;
+                                } else {
+                                    if(last.expires.before(cdd.expires)) {
+                                        last = cdd;
+                                        lastIdx = e;
+                                    }
+                                }
+                            }
+                            ++e;
+                        }
+                        if(last!=null) {
+                            return Result.ok(lastIdx);
+                        }
+                        return Result.err(Status.ERR_BadData, "User chose unknown Tag");
+                    }
+                }
+                entry = Integer.parseInt(inputOption) - 1;
+            }
+            if (entry < 0 || entry >= lcd.size()) {
+                return Result.err(Status.ERR_BadData, "User chose invalid credential selection");
+            }
+        }
+        return Result.ok(entry);
+    }
+
+    private List<CredDAO.Data> filterList(List<CredDAO.Data> orig, Integer ... types) {
+        List<CredDAO.Data> rv = new ArrayList<>();
+        for(CredDAO.Data cdd : orig) {
+            if(cdd!=null) {
+                for(int t : types) {
+                    if(t==cdd.type) {
+                           rv.add(cdd);
+                    }
+                }
+            }
+        }
+        Collections.sort(rv, (o1,o2) -> {
+            if(o1.type==o2.type) {
+                return o1.expires.compareTo(o2.expires);
+            } else {
+                return o1.type.compareTo(o2.type);
+            }
+        });
+        return rv;
+    }
+
+    private String[] buildVariables(List<CredDAO.Data> value) {
+        String [] vars = new String[value.size()];
+        CredDAO.Data cdd;
+
+        for (int i = 0; i < value.size(); i++) {
+            cdd = value.get(i);
+            vars[i] = cdd.id + TWO_SPACE + Define.getCredType(cdd.type) + TWO_SPACE + Chrono.niceUTCStamp(cdd.expires) + TWO_SPACE + cdd.tag;
+        }
+        return vars;
     }
 
+    private String selectCredFromList(List<CredDAO.Data> value, String action) {
+        StringBuilder errMessage = new StringBuilder();
+        String userPrompt = MayChangeCred.DELETE.equals(action)?
+                "Select which cred to delete (set force=true to delete all):":
+                "Select which cred to " + action + ':';
+        int numSpaces = value.get(0).id.length() - "Id".length();
+
+        errMessage.append(userPrompt + '\n');
+        errMessage.append("        ID");
+        for (int i = 0; i < numSpaces; i++) {
+            errMessage.append(' ');
+        }
+        errMessage.append("  Type  Expires               Tag " + '\n');
+        for (int i=0;i<value.size();++i) {
+            errMessage.append("    %s\n");
+        }
+        if(MayChangeCred.EXTEND.equals(action)) {
+            errMessage.append("Run same command again with chosen entry or Tag as last parameter");
+        } else {
+            errMessage.append("Run same command again with chosen entry as last parameter");
+        }
+        return errMessage.toString();
+
+    }
 
     @Override
     public Result<Date> doesCredentialMatch(AuthzTrans trans, REQUEST credReq) {
@@ -2933,11 +3148,11 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         try {
             // Note: Mapper assigns RAW type
             Result<CredDAO.Data> data = mapper.cred(trans, credReq,false);
-            if(data.notOKorIsEmpty()) {
+            if (data.notOKorIsEmpty()) {
                 return Result.err(data);
             }
             CredDAO.Data cred = data.value;    // of the Mapped Cred
-            if(cred.cred==null) {
+            if (cred.cred==null) {
                 return Result.err(Result.ERR_BadData,"No Password");
             } else {
                 return ques.doesUserCredMatch(trans, cred.id, cred.cred.array());
@@ -2951,28 +3166,12 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         }
     }
 
-    @ApiDoc( 
-            method = GET,  
-            path = "/authn/basicAuth",
-            params = {},
-            expectedCode = 200,
-            errorCodes = { 403 }, 
-            text = { "!!!! DEPRECATED without X509 Authentication STOP USING THIS API BY DECEMBER 2017, or use Certificates !!!!\n" 
-                    + "Use /authn/validate instead\n"
-                    + "Note: Validate a Password using BasicAuth Base64 encoded Header. This HTTP/S call is intended as a fast"
-                    + " User/Password lookup for Security Frameworks, and responds 200 if it passes BasicAuth "
-                + "security, and 403 if it does not." }
-            )
-    private void basicAuth() {
-        // This is a place holder for Documentation.  The real BasicAuth API does not call Service.
-    }
-    
-    @ApiDoc( 
-            method = POST,  
+    @ApiDoc(
+            method = POST,
             path = "/authn/validate",
             params = {},
             expectedCode = 200,
-            errorCodes = { 403 }, 
+            errorCodes = { 403 },
             text = { "Validate a Credential given a Credential Structure.  This is a more comprehensive validation, can "
                     + "do more than BasicAuth as Credential types exp" }
             )
@@ -2984,7 +3183,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             BasicPrincipal bp = new BasicPrincipal(basicAuth,trans.org().getRealm());
             Result<Date> rq = ques.doesUserCredMatch(trans, bp.getName(), bp.getCred());
             // Note: Only want to log problem, don't want to send back to end user
-            if(rq.isOK()) {
+            if (rq.isOK()) {
                 return rq;
             } else {
                 trans.audit().log(rq.errorString());
@@ -2997,15 +3196,31 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         return Result.err(Status.ERR_Denied,"Bad Basic Auth");
     }
 
+@ApiDoc(
+            method = GET,
+            path = "/authn/basicAuth",
+            params = {},
+            expectedCode = 200,
+            errorCodes = { 403 },
+            text = { "!!!! DEPRECATED without X509 Authentication STOP USING THIS API BY DECEMBER 2017, or use Certificates !!!!\n"
+                    + "Use /authn/validate instead\n"
+                    + "Note: Validate a Password using BasicAuth Base64 encoded Header. This HTTP/S call is intended as a fast"
+                    + " User/Password lookup for Security Frameworks, and responds 200 if it passes BasicAuth "
+                + "security, and 403 if it does not." }
+            )
+    private void basicAuth() {
+        // This is a place holder for Documentation.  The real BasicAuth API does not call Service.
+    }
+
 /***********************************
- * USER-ROLE 
+ * USER-ROLE
  ***********************************/
-    @ApiDoc( 
-            method = POST,  
+    @ApiDoc(
+            method = POST,
             path = "/authz/userRole",
             params = {},
             expectedCode = 201,
-            errorCodes = {403,404,406,409}, 
+            errorCodes = {403,404,406,409},
             text = { "Create a UserRole relationship (add User to Role)",
                      "A UserRole is an object Representation of membership of a Role for limited time.",
                      "If a shorter amount of time for Role ownership is required, use the 'End' field.",
@@ -3018,55 +3233,62 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         TimeTaken tt = trans.start("Create UserRole", Env.SUB);
         try {
             Result<UserRoleDAO.Data> urr = mapper.userRole(trans, from);
-            if(urr.notOKorIsEmpty()) {
+            if (urr.notOKorIsEmpty()) {
                 return Result.err(urr);
             }
             final UserRoleDAO.Data userRole = urr.value;
-            
+
             final ServiceValidator v = new ServiceValidator();
-            if(v.user_role(userRole).err() ||
+            if (v.user_role(trans.user(),userRole).err() ||
                v.user(trans.org(), userRole.user).err()) {
                 return Result.err(Status.ERR_BadData,v.errs());
             }
 
 
-             
+
             // Check if user can change first
             Result<FutureDAO.Data> fd = mapper.future(trans,UserRoleDAO.TABLE,from,urr.value,true, // may request Approvals
-                new Mapper.Memo() {
-                    @Override
-                    public String get() {
-                        return "Add User [" + userRole.user + "] to Role [" + 
-                                userRole.role + 
-                                ']';
-                    }
-                },
+                () -> "Add User [" + userRole.user + "] to Role [" +
+                        userRole.role +
+                        ']',
                 new MayChange() {
                     private Result<NsDAO.Data> nsd;
                     @Override
                     public Result<?> mayChange() {
-                        if(nsd==null) {
+                        if(urr.value.role.startsWith(urr.value.user)) {
+                            return Result.ok((NsDAO.Data)null);
+                        }
+                        if (nsd==null) {
                             RoleDAO.Data r = RoleDAO.Data.decode(userRole);
                             nsd = ques.mayUser(trans, trans.user(), r, Access.write);
                         }
                         return nsd;
                     }
                 });
-            Result<NsDAO.Data> nsr = ques.deriveNs(trans, userRole.role);
-            if(nsr.notOKorIsEmpty()) {
-                return Result.err(nsr);
+
+            NsDAO.Data ndd;
+            if(userRole.role.startsWith(userRole.user)) {
+                userRole.ns=userRole.user;
+                userRole.rname="user";
+                ndd = null;
+            } else {
+                Result<NsDAO.Data> nsr = ques.deriveNs(trans, userRole.role);
+                if (nsr.notOK()) {
+                    return Result.err(nsr);
+                }
+                ndd = nsr.value;
             }
 
             switch(fd.status) {
                 case OK:
-                    Result<String> rfc = func.createFuture(trans, fd.value, userRole.user+'|'+userRole.ns + '.' + userRole.rname, 
-                            userRole.user, nsr.value, FUTURE_OP.C);
-                    if(rfc.isOK()) {
+                    Result<String> rfc = func.createFuture(trans, fd.value, userRole.user+'|'+userRole.ns + '.' + userRole.rname,
+                            userRole.user, ndd, FUTURE_OP.C);
+                    if (rfc.isOK()) {
                         return Result.err(Status.ACC_Future, "UserRole [%s - %s.%s] is saved for future processing",
                                 userRole.user,
                                 userRole.ns,
                                 userRole.rname);
-                    } else { 
+                    } else {
                         return Result.err(rfc);
                     }
                 case Status.ACC_Now:
@@ -3078,7 +3300,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             tt.done();
         }
     }
-    
+
         /**
          * getUserRolesByRole
          */
@@ -3094,13 +3316,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         @Override
         public Result<USERROLES> getUserRolesByRole(AuthzTrans trans, String role) {
             final Validator v = new ServiceValidator();
-            if(v.nullOrBlank("Role",role).err()) {
+            if (v.nullOrBlank("Role",role).err()) {
                 return Result.err(Status.ERR_BadData,v.errs());
             }
-            
+
             Result<RoleDAO.Data> rrdd;
             rrdd = RoleDAO.Data.decode(trans,ques,role);
-            if(rrdd.notOK()) {
+            if (rrdd.notOK()) {
                 return Result.err(rrdd);
             }
             // May Requester see result?
@@ -3108,20 +3330,20 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             if (ns.notOK()) {
                 return Result.err(ns);
             }
-    
-    //        boolean filter = true;        
+
+    //        boolean filter = true;
     //        if (ns.value.isAdmin(trans.user()) || ns.value.isResponsible(trans.user()))
     //            filter = false;
-            
+
             // Get list of roles per user, then add to Roles as we go
             HashSet<UserRoleDAO.Data> userSet = new HashSet<>();
-            Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByRole(trans, role);
-            if(rlurd.isOK()) {
-                for(UserRoleDAO.Data data : rlurd.value) {
+            Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByRole(trans, role);
+            if (rlurd.isOK()) {
+                for (UserRoleDAO.Data data : rlurd.value) {
                     userSet.add(data);
                 }
             }
-            
+
             @SuppressWarnings("unchecked")
             USERROLES users = (USERROLES) mapper.newInstance(API.USER_ROLES);
             // Checked for permission
@@ -3143,37 +3365,37 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         @Override
         public Result<USERROLES> getUserRolesByUser(AuthzTrans trans, String user) {
             final Validator v = new ServiceValidator();
-            if(v.nullOrBlank("User",user).err()) {
+            if (v.nullOrBlank("User",user).err()) {
                 return Result.err(Status.ERR_BadData,v.errs());
             }
-            
+
             // Get list of roles per user, then add to Roles as we go
-            Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByUser(trans, user);
-            if(rlurd.notOK()) { 
+            Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, user);
+            if (rlurd.notOK()) {
                 return Result.err(rlurd);
             }
-            
+
             /* Check for
-             *   1) is User 
+             *   1) is User
              *   2) is User's Supervisor
              *   3) Has special global access =read permission
-             *   
+             *
              *   If none of the 3, then filter results to NSs in which Calling User has Ns.access * read
              */
             boolean mustFilter;
             String callingUser = trans.getUserPrincipal().getName();
             NsDAO.Data ndd = new NsDAO.Data();
 
-            if(user.equals(callingUser)) {
+            if (user.equals(callingUser)) {
                 mustFilter = false;
             } else {
                 Organization org = trans.org();
                 try {
                     Identity orgID = org.getIdentity(trans, user);
                     Identity manager = orgID==null?null:orgID.responsibleTo();
-                    if(orgID!=null && (manager!=null && callingUser.equals(manager.fullID()))) {
+                    if (orgID!=null && (manager!=null && callingUser.equals(manager.fullID()))) {
                         mustFilter = false;
-                    } else if(ques.isGranted(trans, callingUser, ROOT_NS, Question.ACCESS, "*", Access.read.name())) {
+                    } else if (ques.isGranted(trans, callingUser, ROOT_NS, Question.ACCESS, "*", Access.read.name())) {
                         mustFilter=false;
                     } else {
                         mustFilter = true;
@@ -3183,19 +3405,19 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     mustFilter = true;
                 }
             }
-            
+
             List<UserRoleDAO.Data> content;
-            if(mustFilter) {
+            if (mustFilter) {
                 content = new ArrayList<>(rlurd.value.size()); // avoid multi-memory redos
-                
-                for(UserRoleDAO.Data data : rlurd.value) {
+
+                for (UserRoleDAO.Data data : rlurd.value) {
                     ndd.name=data.ns;
                     Result<Data> mur = ques.mayUser(trans, callingUser, ndd, Access.read);
-                    if(mur.isOK()){
+                    if (mur.isOK()){
                         content.add(data);
                     }
                 }
-                
+
             } else {
                 content = rlurd.value;
             }
@@ -3208,173 +3430,10 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             return Result.ok(users);
         }
 
-        
-    @ApiDoc( 
-            method = PUT,  
-            path = "/authz/userRole/user",
-            params = {},
-            expectedCode = 200,
-            errorCodes = {403,404,406}, 
-            text = { "Set a User's roles to the roles specified in the UserRoleRequest object.",
-                        "WARNING: Roles supplied will be the ONLY roles attached to this user",
-                        "If no roles are supplied, user's roles are reset."
-                   }
-            )
-    @Override
-    public Result<Void> resetRolesForUser(AuthzTrans trans, REQUEST rreq) {
-        Result<UserRoleDAO.Data> rurdd = mapper.userRole(trans, rreq);
-        final ServiceValidator v = new ServiceValidator();
-        if(rurdd.notOKorIsEmpty()) {
-            return Result.err(rurdd);
-        }
-        if (v.user(trans.org(), rurdd.value.user).err()) {
-            return Result.err(Status.ERR_BadData,v.errs());
-        }
-
-        Set<String> currRoles = new HashSet<>();
-        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByUser(trans, rurdd.value.user);
-        if(rlurd.isOK()) {
-            for(UserRoleDAO.Data data : rlurd.value) {
-                currRoles.add(data.role);
-            }
-        }
-        
-        Result<Void> rv = null;
-        String[] roles;
-        if(rurdd.value.role==null) {
-            roles = new String[0];
-        } else {
-            roles = rurdd.value.role.split(",");
-        }
-        
-        for (String role : roles) {            
-            if (v.role(role).err()) {
-                return Result.err(Status.ERR_BadData,v.errs());
-            }
-            Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans, ques, role);
-            if(rrdd.notOK()) {
-                return Result.err(rrdd);
-            }
-            
-            rurdd.value.role(rrdd.value);
-            
-            Result<NsDAO.Data> nsd = ques.mayUser(trans, trans.user(), rrdd.value,Access.write);
-            if (nsd.notOK()) {
-                return Result.err(nsd);
-            }
-            Result<NsDAO.Data> nsr = ques.deriveNs(trans, role);
-            if(nsr.notOKorIsEmpty()) {
-                return Result.err(nsr);    
-            }
-            
-            if(currRoles.contains(role)) {
-                currRoles.remove(role);
-            } else {
-                rv = func.addUserRole(trans, rurdd.value);
-                if (rv.notOK()) {
-                    return rv;
-                }
-            }
-        }
-        
-        for (String role : currRoles) {
-            rurdd.value.role(trans,ques,role);
-            rv = ques.userRoleDAO.delete(trans, rurdd.value, false);
-            if(rv.notOK()) {
-                trans.info().log(rurdd.value.user,"/",rurdd.value.role, "expected to be deleted, but does not exist");
-                // return rv; // if it doesn't exist, don't error out
-            }
-
-        }
-    
-        return Result.ok();        
-        
-    }
-    
-    @ApiDoc( 
-            method = PUT,  
-            path = "/authz/userRole/role",
-            params = {},
-            expectedCode = 200,
-            errorCodes = {403,404,406}, 
-            text = { "Set a Role's users to the users specified in the UserRoleRequest object.",
-                    "WARNING: Users supplied will be the ONLY users attached to this role",
-                    "If no users are supplied, role's users are reset."
-               }
-            )
-    @Override
-    public Result<Void> resetUsersForRole(AuthzTrans trans, REQUEST rreq) {
-        Result<UserRoleDAO.Data> rurdd = mapper.userRole(trans, rreq);
-        if(rurdd.notOKorIsEmpty()) {
-            return Result.err(rurdd);
-        }
-        final ServiceValidator v = new ServiceValidator();
-        if (v.user_role(rurdd.value).err()) {
-            return Result.err(Status.ERR_BadData,v.errs());
-        }
-
-        RoleDAO.Data rd = RoleDAO.Data.decode(rurdd.value);
-
-        Result<NsDAO.Data> nsd = ques.mayUser(trans, trans.user(), rd, Access.write);
-        if (nsd.notOK()) {
-            return Result.err(nsd);
-        }
 
-        Result<NsDAO.Data> nsr = ques.deriveNs(trans, rurdd.value.role);
-        if(nsr.notOKorIsEmpty()) {
-            return Result.err(nsr);    
-        }
 
-        Set<String> currUsers = new HashSet<>();
-        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByRole(trans, rurdd.value.role);
-        if(rlurd.isOK()) { 
-            for(UserRoleDAO.Data data : rlurd.value) {
-                currUsers.add(data.user);
-            }
-        }
-    
-        // found when connected remotely to DEVL, can't replicate locally
-        // inconsistent errors with cmd: role user setTo [nothing]
-        // deleteUserRole --> read --> get --> cacheIdx(?)
-        // sometimes returns idx for last added user instead of user passed in
-        // cache bug? 
-        
-        
-        Result<Void> rv = null;
-        String[] users = {};
-        if (rurdd.value.user != null) {
-            users = rurdd.value.user.split(",");
-        }
-        
-        for (String user : users) {            
-            if (v.user(trans.org(), user).err()) {
-                return Result.err(Status.ERR_BadData,v.errs());
-            }
-            rurdd.value.user = user;
 
-            if(currUsers.contains(user)) {
-                currUsers.remove(user);
-            } else {
-                rv = func.addUserRole(trans, rurdd.value);
-                if (rv.notOK()) { 
-                    return rv;
-                }
-            }
-        }
-        
-        for (String user : currUsers) {
-            rurdd.value.user = user; 
-            rv = ques.userRoleDAO.delete(trans, rurdd.value, false);
-            if(rv.notOK()) {
-                trans.info().log(rurdd.value, "expected to be deleted, but not exists");
-                return rv;
-            }
-        }    
-        
-        return Result.ok();            
-    }
-    
-    @ApiDoc(
+     @ApiDoc(
             method = GET,
             path = "/authz/userRole/extend/:user/:role",
             params = {    "user|string|true",
@@ -3390,29 +3449,29 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> extendUserRole(AuthzTrans trans, String user, String role) {
         Organization org = trans.org();
         final ServiceValidator v = new ServiceValidator();
-        if(v.user(org, user)
+        if (v.user(org, user)
             .role(role)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-    
+
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans,ques,role);
-        if(rrdd.notOK()) {
+        if (rrdd.notOK()) {
             return Result.err(rrdd);
         }
-        
+
         Result<NsDAO.Data> rcr = ques.mayUser(trans, trans.user(), rrdd.value, Access.write);
         boolean mayNotChange;
-        if((mayNotChange = rcr.notOK()) && !trans.requested(future)) {
+        if ((mayNotChange = rcr.notOK()) && !trans.requested(future)) {
             return Result.err(rcr);
         }
-        
-        Result<List<UserRoleDAO.Data>> rr = ques.userRoleDAO.read(trans, user,role);
-        if(rr.notOK()) {
+
+        Result<List<UserRoleDAO.Data>> rr = ques.userRoleDAO().read(trans, user,role);
+        if (rr.notOK()) {
             return Result.err(rr);
         }
-        for(UserRoleDAO.Data userRole : rr.value) {
-            if(mayNotChange) { // Function exited earlier if !trans.futureRequested
+        for (UserRoleDAO.Data userRole : rr.value) {
+            if (mayNotChange) { // Function exited earlier if !trans.futureRequested
                 FutureDAO.Data fto = new FutureDAO.Data();
                 fto.target=UserRoleDAO.TABLE;
                 fto.memo = "Extend User ["+userRole.user+"] in Role ["+userRole.role+"]";
@@ -3426,9 +3485,9 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     return Result.err(e);
                 }
 
-                Result<String> rfc = func.createFuture(trans, fto, 
+                Result<String> rfc = func.createFuture(trans, fto,
                         userRole.user+'|'+userRole.role, userRole.user, rcr.value, FUTURE_OP.U);
-                if(rfc.isOK()) {
+                if (rfc.isOK()) {
                     return Result.err(Status.ACC_Future, "UserRole [%s - %s] is saved for future processing",
                             userRole.user,
                             userRole.role);
@@ -3442,53 +3501,53 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         return Result.err(Result.ERR_NotFound,"This user and role doesn't exist");
     }
 
-    @ApiDoc( 
-            method = DELETE,  
+    @ApiDoc(
+            method = DELETE,
             path = "/authz/userRole/:user/:role",
             params = {    "user|string|true",
                         "role|string|true"
                     },
             expectedCode = 200,
-            errorCodes = {403,404,406}, 
+            errorCodes = {403,404,406},
             text = { "Remove Role :role from User :user."
                    }
             )
     @Override
     public Result<Void> deleteUserRole(AuthzTrans trans, String usr, String role) {
         Validator val = new ServiceValidator();
-        if(val.nullOrBlank("User", usr)
+        if (val.nullOrBlank("User", usr)
               .nullOrBlank("Role", role).err()) {
             return Result.err(Status.ERR_BadData, val.errs());
         }
 
         boolean mayNotChange;
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans,ques,role);
-        if(rrdd.notOK()) {
+        if (rrdd.notOK()) {
             return Result.err(rrdd);
         }
-        
+
         RoleDAO.Data rdd = rrdd.value;
         Result<NsDAO.Data> rns = ques.mayUser(trans, trans.user(), rdd, Access.write);
 
         // Make sure we don't delete the last owner of valid NS
-        if(rns.isOKhasData() && Question.OWNER.equals(rdd.name) && ques.countOwner(trans,rdd.ns)<=1) {
+        if (rns.isOKhasData() && Question.OWNER.equals(rdd.name) && ques.countOwner(trans,rdd.ns)<=1) {
             return Result.err(Status.ERR_Denied,"You may not delete the last Owner of " + rdd.ns );
         }
-        
-        if(mayNotChange=rns.notOK()) {
-            if(!trans.requested(future)) {
+
+        if (mayNotChange=rns.notOK()) {
+            if (!trans.requested(future)) {
                 return Result.err(rns);
             }
         }
 
         Result<List<UserRoleDAO.Data>> rulr;
-        if((rulr=ques.userRoleDAO.read(trans, usr, role)).notOKorIsEmpty()) {
+        if ((rulr=ques.userRoleDAO().read(trans, usr, role)).notOKorIsEmpty()) {
             return Result.err(Status.ERR_UserRoleNotFound, "User [ "+usr+" ] is not "
                     + "Assigned to the Role [ " + role + " ]");
         }
 
         UserRoleDAO.Data userRole = rulr.value.get(0);
-        if(mayNotChange) { // Function exited earlier if !trans.futureRequested
+        if (mayNotChange) { // Function exited earlier if !trans.futureRequested
             FutureDAO.Data fto = new FutureDAO.Data();
             fto.target=UserRoleDAO.TABLE;
             fto.memo = "Remove User ["+userRole.user+"] from Role ["+userRole.role+"]";
@@ -3496,108 +3555,108 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             fto.start = now.getTime();
             fto.expires = trans.org().expiration(now, Expiration.Future).getTime();
 
-            Result<String> rfc = func.createFuture(trans, fto, 
+            Result<String> rfc = func.createFuture(trans, fto,
                     userRole.user+'|'+userRole.role, userRole.user, rns.value, FUTURE_OP.D);
-            if(rfc.isOK()) {
-                return Result.err(Status.ACC_Future, "UserRole [%s - %s] is saved for future processing", 
+            if (rfc.isOK()) {
+                return Result.err(Status.ACC_Future, "UserRole [%s - %s] is saved for future processing",
                         userRole.user,
                         userRole.role);
-            } else { 
+            } else {
                 return Result.err(rfc);
             }
         } else {
-            return ques.userRoleDAO.delete(trans, rulr.value.get(0), false);
+            return ques.userRoleDAO().delete(trans, rulr.value.get(0), false);
         }
     }
 
-    @ApiDoc( 
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authz/userRole/:user/:role",
             params = {"user|string|true",
                       "role|string|true"},
             expectedCode = 200,
-            errorCodes = {403,404,406}, 
+            errorCodes = {403,404,406},
             text = { "Returns the User (with Expiration date from listed User/Role) if it exists"
                    }
             )
     @Override
     public Result<USERS> getUserInRole(AuthzTrans trans, String user, String role) {
         final Validator v = new ServiceValidator();
-        if(v.role(role).nullOrBlank("User", user).err()) {
+        if (v.role(role).nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
 //        Result<NsDAO.Data> ns = ques.deriveNs(trans, role);
 //        if (ns.notOK()) return Result.err(ns);
-//        
+//
 //        Result<NsDAO.Data> rnd = ques.mayUser(trans, trans.user(), ns.value, Access.write);
         // May calling user see by virtue of the Role
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans, ques, role);
-        if(rrdd.notOK()) {
+        if (rrdd.notOK()) {
             return Result.err(rrdd);
         }
         Result<NsDAO.Data> rnd = ques.mayUser(trans, trans.user(), rrdd.value,Access.read);
-        if(rnd.notOK()) {
-            return Result.err(rnd); 
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
-        
+
         HashSet<UserRoleDAO.Data> userSet = new HashSet<>();
-        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readUserInRole(trans, user, role);
-        if(rlurd.isOK()) {
-            for(UserRoleDAO.Data data : rlurd.value) {
+        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readUserInRole(trans, user, role);
+        if (rlurd.isOK()) {
+            for (UserRoleDAO.Data data : rlurd.value) {
                 userSet.add(data);
             }
         }
-        
+
         @SuppressWarnings("unchecked")
         USERS users = (USERS) mapper.newInstance(API.USERS);
         mapper.users(trans, userSet, users);
         return Result.ok(users);
     }
 
-    @ApiDoc( 
-            method = GET,  
+    @ApiDoc(
+            method = GET,
             path = "/authz/users/role/:role",
             params = {"user|string|true",
                       "role|string|true"},
             expectedCode = 200,
-            errorCodes = {403,404,406}, 
+            errorCodes = {403,404,406},
             text = { "Returns the User (with Expiration date from listed User/Role) if it exists"
                    }
             )
     @Override
     public Result<USERS> getUsersByRole(AuthzTrans trans, String role) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Role",role).err()) {
+        if (v.nullOrBlank("Role",role).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
 //        Result<NsDAO.Data> ns = ques.deriveNs(trans, role);
 //        if (ns.notOK()) return Result.err(ns);
-//        
+//
 //        Result<NsDAO.Data> rnd = ques.mayUser(trans, trans.user(), ns.value, Access.write);
         // May calling user see by virtue of the Role
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans, ques, role);
-        if(rrdd.notOK()) {
+        if (rrdd.notOK()) {
             return Result.err(rrdd);
         }
-        
+
         boolean contactOnly = false;
         // Allow the request of any valid user to find the contact of the NS (Owner)
         Result<NsDAO.Data> rnd = ques.mayUser(trans, trans.user(), rrdd.value,Access.read);
-        if(rnd.notOK()) {
-            if(Question.OWNER.equals(rrdd.value.name)) {
+        if (rnd.notOK()) {
+            if (Question.OWNER.equals(rrdd.value.name)) {
                 contactOnly = true;
             } else {
                 return Result.err(rnd);
             }
         }
-        
+
         HashSet<UserRoleDAO.Data> userSet = new HashSet<>();
-        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByRole(trans, role);
-        if(rlurd.isOK()) { 
-            for(UserRoleDAO.Data data : rlurd.value) {
-                if(contactOnly) { //scrub data
+        Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByRole(trans, role);
+        if (rlurd.isOK()) {
+            for (UserRoleDAO.Data data : rlurd.value) {
+                if (contactOnly) { //scrub data
                     // Can't change actual object, or will mess up the cache.
                     UserRoleDAO.Data scrub = new UserRoleDAO.Data();
                     scrub.ns = data.ns;
@@ -3610,7 +3669,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                 }
             }
         }
-        
+
         @SuppressWarnings("unchecked")
         USERS users = (USERS) mapper.newInstance(API.USERS);
         mapper.users(trans, userSet, users);
@@ -3635,44 +3694,44 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<USERS> getUsersByPermission(AuthzTrans trans, String type, String instance, String action) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Type",type)
+        if (v.nullOrBlank("Type",type)
             .nullOrBlank("Instance",instance)
-            .nullOrBlank("Action",action)            
+            .nullOrBlank("Action",action)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<NsSplit> nss = ques.deriveNsSplit(trans, type);
-        if(nss.notOK()) {
+        if (nss.notOK()) {
             return Result.err(nss);
         }
-        
-        Result<List<NsDAO.Data>> nsd = ques.nsDAO.read(trans, nss.value.ns);
+
+        Result<List<NsDAO.Data>> nsd = ques.nsDAO().read(trans, nss.value.ns);
         if (nsd.notOK()) {
             return Result.err(nsd);
         }
-        
+
         boolean allInstance = ASTERIX.equals(instance);
         boolean allAction = ASTERIX.equals(action);
-        // Get list of roles per Permission, 
+        // Get list of roles per Permission,
         // Then loop through Roles to get Users
         // Note: Use Sets to avoid processing or responding with Duplicates
         Set<String> roleUsed = new HashSet<>();
         Set<UserRoleDAO.Data> userSet = new HashSet<>();
-        
-        if(!nss.isEmpty()) {
-            Result<List<PermDAO.Data>> rlp = ques.permDAO.readByType(trans, nss.value.ns, nss.value.name);
-            if(rlp.isOKhasData()) {
-                for(PermDAO.Data pd : rlp.value) {
-                    if((allInstance || pd.instance.equals(instance)) && 
+
+        if (!nss.isEmpty()) {
+            Result<List<PermDAO.Data>> rlp = ques.permDAO().readByType(trans, nss.value.ns, nss.value.name);
+            if (rlp.isOKhasData()) {
+                for (PermDAO.Data pd : rlp.value) {
+                    if ((allInstance || pd.instance.equals(instance)) &&
                             (allAction || pd.action.equals(action))) {
-                        if(ques.mayUser(trans, trans.user(),pd,Access.read).isOK()) {
-                            for(String role : pd.roles) {
-                                if(!roleUsed.contains(role)) { // avoid evaluating Role many times
+                        if (ques.mayUser(trans, trans.user(),pd,Access.read).isOK()) {
+                            for (String role : pd.roles) {
+                                if (!roleUsed.contains(role)) { // avoid evaluating Role many times
                                     roleUsed.add(role);
-                                    Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO.readByRole(trans, role.replace('|', '.'));
-                                    if(rlurd.isOKhasData()) {
-                                        for(UserRoleDAO.Data urd : rlurd.value) {
+                                    Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByRole(trans, role.replace('|', '.'));
+                                    if (rlurd.isOKhasData()) {
+                                        for (UserRoleDAO.Data urd : rlurd.value) {
                                             userSet.add(urd);
                                         }
                                     }
@@ -3689,43 +3748,43 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         return Result.ok(users);
     }
 
-    /***********************************
- * HISTORY 
- ***********************************/    
+/***********************************
+ * HISTORY
+ ***********************************/
     @Override
-    public Result<HISTORY> getHistoryByUser(final AuthzTrans trans, String user, final int[] yyyymm, final int sort) {    
+    public Result<HISTORY> getHistoryByUser(final AuthzTrans trans, String user, final int[] yyyymm, final int sort) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User",user).err()) {
+        if (v.nullOrBlank("User",user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<NsDAO.Data> rnd;
         // Users may look at their own data
-         if(trans.user().equals(user)) {
+         if (trans.user().equals(user)) {
                 // Users may look at their own data
          } else {
             int at = user.indexOf('@');
-            if(at>=0 && trans.org().getRealm().equals(user.substring(at+1))) {
+            if (at>=0 && trans.org().getRealm().equals(user.substring(at+1))) {
                 NsDAO.Data nsd  = new NsDAO.Data();
                 nsd.name = Question.domain2ns(user);
                 rnd = ques.mayUser(trans, trans.user(), nsd, Access.read);
-                if(rnd.notOK()) {
+                if (rnd.notOK()) {
                     return Result.err(rnd);
                 }
             } else {
                 rnd = ques.validNSOfDomain(trans, user);
-                if(rnd.notOK()) {
+                if (rnd.notOK()) {
                     return Result.err(rnd);
                 }
 
                 rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
-                if(rnd.notOK()) {
+                if (rnd.notOK()) {
                     return Result.err(rnd);
                 }
             }
          }
-        Result<List<HistoryDAO.Data>> resp = ques.historyDAO.readByUser(trans, user, yyyymm);
-        if(resp.notOK()) {
+        Result<List<HistoryDAO.Data>> resp = ques.historyDAO().readByUser(trans, user, yyyymm);
+        if (resp.notOK()) {
             return Result.err(resp);
         }
         return mapper.history(trans, resp.value,sort);
@@ -3734,21 +3793,21 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<HISTORY> getHistoryByRole(AuthzTrans trans, String role, int[] yyyymm, final int sort) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Role",role).err()) {
+        if (v.nullOrBlank("Role",role).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<RoleDAO.Data> rrdd = RoleDAO.Data.decode(trans, ques, role);
-        if(rrdd.notOK()) {
+        if (rrdd.notOK()) {
             return Result.err(rrdd);
         }
-        
+
         Result<NsDAO.Data> rnd = ques.mayUser(trans, trans.user(), rrdd.value, Access.read);
-        if(rnd.notOK()) {
+        if (rnd.notOK()) {
             return Result.err(rnd);
         }
-        Result<List<HistoryDAO.Data>> resp = ques.historyDAO.readBySubject(trans, role, "role", yyyymm); 
-        if(resp.notOK()) {
+        Result<List<HistoryDAO.Data>> resp = ques.historyDAO().readBySubject(trans, role, "role", yyyymm);
+        if (resp.notOK()) {
             return Result.err(resp);
         }
         return mapper.history(trans, resp.value,sort);
@@ -3757,23 +3816,28 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<HISTORY> getHistoryByPerm(AuthzTrans trans, String type, int[] yyyymm, final int sort) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Type",type)
+        if (v.nullOrBlank("Type",type)
             .err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         // May user see Namespace of Permission (since it's only one piece... we can't check for "is permission part of")
-        Result<NsDAO.Data> rnd = ques.deriveNs(trans,type);
-        if(rnd.notOK()) {
-            return Result.err(rnd);
-        }
-        
-        rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
-        if(rnd.notOK()) {
-            return Result.err(rnd);    
+        Result<List<HistoryDAO.Data>> resp;
+        if(type.startsWith(trans.user())) {
+            resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm);
+        } else {
+            Result<NsDAO.Data> rnd = ques.deriveNs(trans,type);
+            if (rnd.notOK()) {
+                return Result.err(rnd);
+            }
+            rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
+            if (rnd.notOK()) {
+                return Result.err(rnd);
+            }
+            resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm);
         }
-        Result<List<HistoryDAO.Data>> resp = ques.historyDAO.readBySubject(trans, type, "perm", yyyymm);
-        if(resp.notOK()) {
+
+        if (resp.notOK()) {
             return Result.err(resp);
         }
         return mapper.history(trans, resp.value,sort);
@@ -3782,29 +3846,44 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<HISTORY> getHistoryByNS(AuthzTrans trans, String ns, int[] yyyymm, final int sort) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("NS",ns)
-            .err()) { 
+        if (v.nullOrBlank("NS",ns).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         Result<NsDAO.Data> rnd = ques.deriveNs(trans,ns);
-        if(rnd.notOK()) {
+        if (rnd.notOK()) {
             return Result.err(rnd);
         }
         rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read);
-        if(rnd.notOK()) {
-            return Result.err(rnd);    
+        if (rnd.notOK()) {
+            return Result.err(rnd);
+        }
+
+        Result<List<HistoryDAO.Data>> resp = ques.historyDAO().readBySubject(trans, ns, "ns", yyyymm);
+        if (resp.notOK()) {
+            return Result.err(resp);
+        }
+        return mapper.history(trans, resp.value,sort);
+    }
+
+    @Override
+    public Result<HISTORY> getHistoryBySubject(AuthzTrans trans, String subject, String target, int[] yyyymm, final int sort) {
+        NsDAO.Data ndd = new NsDAO.Data();
+        ndd.name = FQI.reverseDomain(subject);
+        Result<Data> rnd = ques.mayUser(trans, trans.user(), ndd, Access.read);
+        if (rnd.notOK()) {
+            return Result.err(rnd);
         }
 
-        Result<List<HistoryDAO.Data>> resp = ques.historyDAO.readBySubject(trans, ns, "ns", yyyymm);
-        if(resp.notOK()) {
+        Result<List<HistoryDAO.Data>> resp = ques.historyDAO().readBySubject(trans, subject, target, yyyymm);
+        if (resp.notOK()) {
             return Result.err(resp);
         }
         return mapper.history(trans, resp.value,sort);
     }
 
 /***********************************
- * DELEGATE 
+ * DELEGATE
  ***********************************/
     @Override
     public Result<Void> createDelegate(final AuthzTrans trans, REQUEST base) {
@@ -3820,66 +3899,64 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     private Result<Void> createOrUpdateDelegate(final AuthzTrans trans, REQUEST base, final Access access) {
         final Result<DelegateDAO.Data> rd = mapper.delegate(trans, base);
         final ServiceValidator v = new ServiceValidator();
-        if(v.delegate(trans.org(),rd).err()) { 
+        if (v.delegate(trans.org(),rd).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         final DelegateDAO.Data dd = rd.value;
         
-        Result<List<DelegateDAO.Data>> ddr = ques.delegateDAO.read(trans, dd);
-        if(access==Access.create && ddr.isOKhasData()) {
+        if(dd.user.contentEquals(dd.delegate) && !trans.requested(force)) {
+               return Result.err(Status.ERR_InvalidDelegate,dd.user + " cannot delegate to self");
+        }
+
+        Result<List<DelegateDAO.Data>> ddr = ques.delegateDAO().read(trans, dd);
+        if (access==Access.create && ddr.isOKhasData()) {
             return Result.err(Status.ERR_ConflictAlreadyExists, "[%s] already delegates to [%s]", dd.user, ddr.value.get(0).delegate);
-        } else if(access!=Access.create && ddr.notOKorIsEmpty()) { 
+        } else if (access!=Access.create && ddr.notOKorIsEmpty()) {
             return Result.err(Status.ERR_NotFound, "[%s] does not have a Delegate Record to [%s].",dd.user,access.name());
         }
         Result<Void> rv = ques.mayUser(trans, dd, access);
-        if(rv.notOK()) {
+        if (rv.notOK()) {
             return rv;
         }
-        
-        Result<FutureDAO.Data> fd = mapper.future(trans,DelegateDAO.TABLE,base, dd, false, 
-            new Mapper.Memo() {
-                @Override
-                public String get() {
-                    StringBuilder sb = new StringBuilder();
-                    sb.append(access.name());
-                    sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
-                    sb.append("Delegate ");
-                    sb.append(access==Access.create?"[":"to [");
-                    sb.append(rd.value.delegate);
-                    sb.append("] for [");
-                    sb.append(rd.value.user);
-                    sb.append(']');
-                    return sb.toString();
-                }
+
+        Result<FutureDAO.Data> fd = mapper.future(trans,DelegateDAO.TABLE,base, dd, false,
+            () -> {
+                StringBuilder sb = new StringBuilder();
+                sb.append(access.name());
+                sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
+                sb.append("Delegate ");
+                sb.append(access==Access.create?"[":"to [");
+                sb.append(rd.value.delegate);
+                sb.append("] for [");
+                sb.append(rd.value.user);
+                sb.append(']');
+                return sb.toString();
             },
-            new MayChange() {
-                @Override
-                public Result<?> mayChange() {
-                    return Result.ok(); // Validate in code above
-                }
+            () -> {
+                return Result.ok(); // Validate in code above
             });
-        
+
         switch(fd.status) {
             case OK:
-                Result<String> rfc = func.createFuture(trans, fd.value, 
+                Result<String> rfc = func.createFuture(trans, fd.value,
                         dd.user, trans.user(),null, access==Access.create?FUTURE_OP.C:FUTURE_OP.U);
-                if(rfc.isOK()) { 
+                if (rfc.isOK()) {
                     return Result.err(Status.ACC_Future, "Delegate for [%s]",
                             dd.user);
-                } else { 
+                } else {
                     return Result.err(rfc);
                 }
             case Status.ACC_Now:
-                if(access==Access.create) {
-                    Result<DelegateDAO.Data> rdr = ques.delegateDAO.create(trans, dd);
-                    if(rdr.isOK()) {
+                if (access==Access.create) {
+                    Result<DelegateDAO.Data> rdr = ques.delegateDAO().create(trans, dd);
+                    if (rdr.isOK()) {
                         return Result.ok();
                     } else {
                         return Result.err(rdr);
                     }
                 } else {
-                    return ques.delegateDAO.update(trans, dd);
+                    return ques.delegateDAO().update(trans, dd);
                 }
             default:
                 return Result.err(fd);
@@ -3890,48 +3967,48 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     public Result<Void> deleteDelegate(AuthzTrans trans, REQUEST base) {
         final Result<DelegateDAO.Data> rd = mapper.delegate(trans, base);
         final Validator v = new ServiceValidator();
-        if(v.notOK(rd).nullOrBlank("User", rd.value.user).err()) {
+        if (v.notOK(rd).nullOrBlank("User", rd.value.user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         Result<List<DelegateDAO.Data>> ddl;
-        if((ddl=ques.delegateDAO.read(trans, rd.value)).notOKorIsEmpty()) {
+        if ((ddl=ques.delegateDAO().read(trans, rd.value)).notOKorIsEmpty()) {
             return Result.err(Status.ERR_DelegateNotFound,"Cannot delete non-existent Delegate");
         }
         final DelegateDAO.Data dd = ddl.value.get(0);
         Result<Void> rv = ques.mayUser(trans, dd, Access.write);
-        if(rv.notOK()) {
+        if (rv.notOK()) {
             return rv;
         }
-        
-        return ques.delegateDAO.delete(trans, dd, false);
+
+        return ques.delegateDAO().delete(trans, dd, false);
     }
 
     @Override
     public Result<Void> deleteDelegate(AuthzTrans trans, String userName) {
         DelegateDAO.Data dd = new DelegateDAO.Data();
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User", userName).err()) {
+        if (v.nullOrBlank("User", userName).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         dd.user = userName;
         Result<List<DelegateDAO.Data>> ddl;
-        if((ddl=ques.delegateDAO.read(trans, dd)).notOKorIsEmpty()) {
+        if ((ddl=ques.delegateDAO().read(trans, dd)).notOKorIsEmpty()) {
             return Result.err(Status.ERR_DelegateNotFound,"Cannot delete non-existent Delegate");
         }
         dd = ddl.value.get(0);
         Result<Void> rv = ques.mayUser(trans, dd, Access.write);
-        if(rv.notOK()) {
+        if (rv.notOK()) {
             return rv;
         }
-        
-        return ques.delegateDAO.delete(trans, dd, false);
+
+        return ques.delegateDAO().delete(trans, dd, false);
     }
-    
+
     @Override
     public Result<DELGS> getDelegatesByUser(AuthzTrans trans, String user) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User", user).err()) {
+        if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
@@ -3939,13 +4016,13 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         ddd.user = user;
         ddd.delegate = null;
         Result<Void> rv = ques.mayUser(trans, ddd, Access.read);
-        if(rv.notOK()) {
+        if (rv.notOK()) {
             return Result.err(rv);
         }
-        
+
         TimeTaken tt = trans.start("Get delegates for a user", Env.SUB);
 
-        Result<List<DelegateDAO.Data>> dbDelgs = ques.delegateDAO.read(trans, user);
+        Result<List<DelegateDAO.Data>> dbDelgs = ques.delegateDAO().read(trans, user);
         try {
             if (dbDelgs.isOKhasData()) {
                 return mapper.delegate(dbDelgs.value);
@@ -3954,26 +4031,26 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             }
         } finally {
             tt.done();
-        }        
+        }
     }
 
     @Override
     public Result<DELGS> getDelegatesByDelegate(AuthzTrans trans, String delegate) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Delegate", delegate).err()) {
+        if (v.nullOrBlank("Delegate", delegate).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
         DelegateDAO.Data ddd = new DelegateDAO.Data();
         ddd.user = delegate;
         Result<Void> rv = ques.mayUser(trans, ddd, Access.read);
-        if(rv.notOK()) {
+        if (rv.notOK()) {
             return Result.err(rv);
         }
 
         TimeTaken tt = trans.start("Get users for a delegate", Env.SUB);
 
-        Result<List<DelegateDAO.Data>> dbDelgs = ques.delegateDAO.readByDelegate(trans, delegate);
+        Result<List<DelegateDAO.Data>> dbDelgs = ques.delegateDAO().readByDelegate(trans, delegate);
         try {
             if (dbDelgs.isOKhasData()) {
                 return mapper.delegate(dbDelgs.value);
@@ -3982,63 +4059,59 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             }
         } finally {
             tt.done();
-        }        
+        }
     }
 
 /***********************************
- * APPROVAL 
+ * APPROVAL
  ***********************************/
     private static final String APPR_FMT = "actor=%s, action=%s, operation=\"%s\", requestor=%s, delegator=%s";
     @Override
     public Result<Void> updateApproval(AuthzTrans trans, APPROVALS approvals) {
         Result<List<ApprovalDAO.Data>> rlad = mapper.approvals(approvals);
-        if(rlad.notOK()) {
+        if (rlad.notOK()) {
             return Result.err(rlad);
         }
         int numApprs = rlad.value.size();
-        if(numApprs<1) {
+        if (numApprs<1) {
             return Result.err(Status.ERR_NoApprovals,"No Approvals sent for Updating");
         }
         int numProcessed = 0;
         String user = trans.user();
-        
+
         Result<List<ApprovalDAO.Data>> curr;
         Lookup<List<ApprovalDAO.Data>> apprByTicket=null;
-        for(ApprovalDAO.Data updt : rlad.value) {
-            if(updt.ticket!=null) {
-                curr = ques.approvalDAO.readByTicket(trans, updt.ticket);
-                if(curr.isOKhasData()) {
+        for (ApprovalDAO.Data updt : rlad.value) {
+            if (updt.ticket!=null) {
+                curr = ques.approvalDAO().readByTicket(trans, updt.ticket);
+                if (curr.isOKhasData()) {
                     final List<ApprovalDAO.Data> add = curr.value;
-                    apprByTicket = new Lookup<List<ApprovalDAO.Data>>() { // Store a Pre-Lookup
-                        @Override
-                        public List<ApprovalDAO.Data> get(AuthzTrans trans, Object ... noop) {
-                            return add;
-                        }
-                    };
+                    // Store a Pre-Lookup
+                    apprByTicket = (trans1, noop) -> add;
                 }
-            } else if(updt.id!=null) {
-                curr = ques.approvalDAO.read(trans, updt);
-            } else if(updt.approver!=null) {
-                curr = ques.approvalDAO.readByApprover(trans, updt.approver);
+            } else if (updt.id!=null) {
+                curr = ques.approvalDAO().read(trans, updt);
+            } else if (updt.approver!=null) {
+                curr = ques.approvalDAO().readByApprover(trans, updt.approver);
             } else {
                 return Result.err(Status.ERR_BadData,"Approvals need ID, Ticket or Approval data to update");
             }
 
-            if(curr.isOKhasData()) {
+            if (curr.isOKhasData()) {
                 Map<String, Result<List<DelegateDAO.Data>>> delegateCache = new HashMap<>();
                 Map<UUID, FutureDAO.Data> futureCache = new HashMap<>();
                 FutureDAO.Data hasDeleted = new FutureDAO.Data();
-                
-                for(ApprovalDAO.Data cd : curr.value) {
-                    if("pending".equals(cd.status)) {
+
+                for (ApprovalDAO.Data cd : curr.value) {
+                    if ("pending".equals(cd.status)) {
                         // Check for right record.  Need ID, or (Ticket&Trans.User==Appr)
                         // If Default ID
                         boolean delegatedAction = ques.isDelegated(trans, user, cd.approver, delegateCache);
                         String delegator = cd.approver;
-                        if(updt.id!=null || 
+                        if (updt.id!=null ||
                             (updt.ticket!=null && user.equals(cd.approver)) ||
                             (updt.ticket!=null && delegatedAction)) {
-                            if(updt.ticket.equals(cd.ticket)) {
+                            if (updt.ticket.equals(cd.ticket)) {
                                 Changed ch = new Changed();
                                 cd.id = ch.changed(cd.id,updt.id);
 //                                cd.ticket = changed(cd.ticket,updt.ticket);
@@ -4049,29 +4122,29 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                                 cd.memo = ch.changed(cd.memo,updt.memo);
                                 cd.operation = ch.changed(cd.operation,updt.operation);
                                 cd.updated = ch.changed(cd.updated,updt.updated==null?new Date():updt.updated);
-                                if(updt.status.equals("denied")) {
-                                    cd.last_notified = null;
-                                }
-                                if(cd.ticket!=null) {
+//                                if (updt.status.equals("denied")) {
+//                                    cd.last_notified = null;
+//                                }
+                                if (cd.ticket!=null) {
                                     FutureDAO.Data fdd = futureCache.get(cd.ticket);
-                                    if(fdd==null) { // haven't processed ticket yet
-                                        Result<FutureDAO.Data> rfdd = ques.futureDAO.readPrimKey(trans, cd.ticket);
-                                        if(rfdd.isOK()) {
+                                    if (fdd==null) { // haven't processed ticket yet
+                                        Result<FutureDAO.Data> rfdd = ques.futureDAO().readPrimKey(trans, cd.ticket);
+                                        if (rfdd.isOK()) {
                                             fdd = rfdd.value; // null is ok
                                         } else {
                                             fdd = hasDeleted;
                                         }
                                         futureCache.put(cd.ticket, fdd); // processed this Ticket... don't do others on this ticket
                                     }
-                                    if(fdd==hasDeleted) { // YES, by Object
+                                    if (fdd==hasDeleted) { // YES, by Object
                                         cd.ticket = null;
                                         cd.status = "ticketDeleted";
                                         ch.hasChanged(true);
                                     } else {
                                         FUTURE_OP fop = FUTURE_OP.toFO(cd.operation);
-                                        if(fop==null) {
+                                        if (fop==null) {
                                             trans.info().printf("Approval Status %s is not actionable",cd.status);
-                                        } else if(apprByTicket!=null) {
+                                        } else if (apprByTicket!=null) {
                                             Result<OP_STATUS> rv = func.performFutureOp(trans, fop, fdd, apprByTicket,func.urDBLookup);
                                             if (rv.isOK()) {
                                                 switch(rv.value) {
@@ -4097,8 +4170,8 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                                     }
                                     ++numProcessed;
                                 }
-                                if(ch.hasChanged()) {
-                                    ques.approvalDAO.update(trans, cd, true);
+                                if (ch.hasChanged()) {
+                                    ques.approvalDAO().update(trans, cd, true);
                                 }
                             }
                         }
@@ -4107,18 +4180,18 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
             }
         }
 
-        if(numApprs==numProcessed) {
+        if (numApprs==numProcessed) {
             return Result.ok();
         }
         return Result.err(Status.ERR_ActionNotCompleted,numProcessed + " out of " + numApprs + " completed");
 
     }
-    
+
     private static class Changed {
         private boolean hasChanged = false;
 
         public<T> T changed(T src, T proposed) {
-            if(proposed==null || (src!=null && src.equals(proposed))) {
+            if (proposed==null || (src!=null && src.equals(proposed))) {
                 return src;
             }
             hasChanged=true;
@@ -4137,12 +4210,12 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<APPROVALS> getApprovalsByUser(AuthzTrans trans, String user) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("User", user).err()) { 
+        if (v.nullOrBlank("User", user).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
 
-        Result<List<ApprovalDAO.Data>> rapd = ques.approvalDAO.readByUser(trans, user);
-        if(rapd.isOK()) {
+        Result<List<ApprovalDAO.Data>> rapd = ques.approvalDAO().readByUser(trans, user);
+        if (rapd.isOK()) {
             return mapper.approvals(rapd.value);
         } else {
             return Result.err(rapd);
@@ -4152,7 +4225,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
     @Override
     public Result<APPROVALS> getApprovalsByTicket(AuthzTrans trans, String ticket) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Ticket", ticket).err()) { 
+        if (v.nullOrBlank("Ticket", ticket).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
         UUID uuid;
@@ -4161,39 +4234,39 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         } catch (IllegalArgumentException e) {
             return Result.err(Status.ERR_BadData,e.getMessage());
         }
-    
-        Result<List<ApprovalDAO.Data>> rapd = ques.approvalDAO.readByTicket(trans, uuid);
-        if(rapd.isOK()) {
+
+        Result<List<ApprovalDAO.Data>> rapd = ques.approvalDAO().readByTicket(trans, uuid);
+        if (rapd.isOK()) {
             return mapper.approvals(rapd.value);
         } else {
             return Result.err(rapd);
         }
     }
-    
+
     @Override
     public Result<APPROVALS> getApprovalsByApprover(AuthzTrans trans, String approver) {
         final Validator v = new ServiceValidator();
-        if(v.nullOrBlank("Approver", approver).err()) {
+        if (v.nullOrBlank("Approver", approver).err()) {
             return Result.err(Status.ERR_BadData,v.errs());
         }
-        
+
         List<ApprovalDAO.Data> listRapds = new ArrayList<>();
-        
-        Result<List<ApprovalDAO.Data>> myRapd = ques.approvalDAO.readByApprover(trans, approver);
-        if(myRapd.notOK()) {
+
+        Result<List<ApprovalDAO.Data>> myRapd = ques.approvalDAO().readByApprover(trans, approver);
+        if (myRapd.notOK()) {
             return Result.err(myRapd);
         }
-        
+
         listRapds.addAll(myRapd.value);
-        
-        Result<List<DelegateDAO.Data>> delegatedFor = ques.delegateDAO.readByDelegate(trans, approver);
+
+        Result<List<DelegateDAO.Data>> delegatedFor = ques.delegateDAO().readByDelegate(trans, approver);
         if (delegatedFor.isOK()) {
             for (DelegateDAO.Data dd : delegatedFor.value) {
                 if (dd.expires.after(new Date())) {
                     String delegator = dd.user;
-                    Result<List<ApprovalDAO.Data>> rapd = ques.approvalDAO.readByApprover(trans, delegator);
+                    Result<List<ApprovalDAO.Data>> rapd = ques.approvalDAO().readByApprover(trans, delegator);
                     if (rapd.isOK()) {
-                        for (ApprovalDAO.Data d : rapd.value) { 
+                        for (ApprovalDAO.Data d : rapd.value) {
                             if (!d.user.equals(trans.user())) {
                                 listRapds.add(d);
                             }
@@ -4202,16 +4275,16 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                 }
             }
         }
-        
+
         return mapper.approvals(listRapds);
     }
-    
+
     /* (non-Javadoc)
      * @see org.onap.aaf.auth.service.AuthzService#clearCache(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.String)
      */
     @Override
     public Result<Void> cacheClear(AuthzTrans trans, String cname) {
-        if(ques.isGranted(trans,trans.user(),ROOT_NS,CACHE,cname,"clear")) {
+        if (ques.isGranted(trans,trans.user(),ROOT_NS,CACHE,cname,"clear")) {
             return ques.clearCache(trans,cname);
         }
         return Result.err(Status.ERR_Denied, "%s does not have AAF Permission '%s.%s|%s|clear",
@@ -4223,12 +4296,12 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
      */
     @Override
     public Result<Void> cacheClear(AuthzTrans trans, String cname, int[] segment) {
-        if(ques.isGranted(trans,trans.user(),ROOT_NS,CACHE,cname,"clear")) {
+        if (ques.isGranted(trans,trans.user(),ROOT_NS,CACHE,cname,"clear")) {
             Result<Void> v=null;
-            for(int i: segment) {
+            for (int i: segment) {
                 v=ques.cacheClear(trans,cname,i);
             }
-            if(v!=null) {
+            if (v!=null) {
                 return v;
             }
         }
@@ -4241,7 +4314,7 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
      */
     @Override
     public void dbReset(AuthzTrans trans) {
-        ques.historyDAO.reportPerhapsReset(trans, null);
+        ques.historyDAO().reportPerhapsReset(trans, null);
     }
 
 }