RANGER-278 move validation classes under 
org.apache.ranger.plugin.model.validation

Signed-off-by: Madhan Neethiraj <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/7bb68687
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/7bb68687
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/7bb68687

Branch: refs/heads/master
Commit: 7bb686873805b8157644dbd3e9e27632ef8c5590
Parents: 9b35976
Author: Alok Lal <[email protected]>
Authored: Sat Mar 14 08:09:54 2015 -0700
Committer: Madhan Neethiraj <[email protected]>
Committed: Sat Mar 14 11:41:44 2015 -0700

----------------------------------------------------------------------
 .../model/validation/RangerPolicyValidator.java | 496 ++++++++++++++++++
 .../validation/RangerServiceDefValidator.java   | 365 +++++++++++++
 .../validation/RangerServiceValidator.java      | 207 ++++++++
 .../model/validation/RangerValidator.java       | 480 +++++++++++++++++
 .../validation/RangerValidatorFactory.java      |  36 ++
 .../validation/ValidationFailureDetails.java    |  91 ++++
 .../ValidationFailureDetailsBuilder.java        |  64 +++
 .../validation/TestRangerPolicyValidator.java   | 524 +++++++++++++++++++
 .../TestRangerServiceDefValidator.java          | 355 +++++++++++++
 .../validation/TestRangerServiceValidator.java  | 240 +++++++++
 .../model/validation/TestRangerValidator.java   | 476 +++++++++++++++++
 .../model/validation/ValidationTestUtils.java   | 371 +++++++++++++
 .../ranger/rest/RangerPolicyValidator.java      | 496 ------------------
 .../ranger/rest/RangerServiceDefValidator.java  | 365 -------------
 .../ranger/rest/RangerServiceValidator.java     | 207 --------
 .../org/apache/ranger/rest/RangerValidator.java | 480 -----------------
 .../ranger/rest/RangerValidatorFactory.java     |  36 --
 .../org/apache/ranger/rest/ServiceREST.java     |   6 +-
 .../ranger/rest/ValidationFailureDetails.java   |  91 ----
 .../rest/ValidationFailureDetailsBuilder.java   |  64 ---
 .../ranger/rest/TestRangerPolicyValidator.java  | 524 -------------------
 .../rest/TestRangerServiceDefValidator.java     | 355 -------------
 .../ranger/rest/TestRangerServiceValidator.java | 240 ---------
 .../apache/ranger/rest/TestRangerValidator.java | 476 -----------------
 .../rest/TestServiceRESTForValidation.java      |   6 +-
 .../apache/ranger/rest/ValidationTestUtils.java | 371 -------------
 26 files changed, 3715 insertions(+), 3707 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
new file mode 100644
index 0000000..f5d6bff
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
@@ -0,0 +1,496 @@
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerPolicyValidator extends RangerValidator {
+
+       private static final Log LOG = 
LogFactory.getLog(RangerPolicyValidator.class);
+
+       public RangerPolicyValidator(ServiceStore store) {
+               super(store);
+       }
+
+       public void validate(RangerPolicy policy, Action action) throws 
Exception {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.validate(%s, %s)", policy, action));
+               }
+
+               List<ValidationFailureDetails> failures = new 
ArrayList<ValidationFailureDetails>();
+               boolean valid = isValid(policy, action, failures);
+               String message = "";
+               try {
+                       if (!valid) {
+                               message = serializeFailures(failures);
+                               throw new Exception(message);
+                       }
+               } finally {
+                       if(LOG.isDebugEnabled()) {
+                               LOG.debug(String.format("<== 
RangerPolicyValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, 
message));
+                       }
+               }
+       }
+
+       @Override
+       boolean isValid(Long id, Action action, List<ValidationFailureDetails> 
failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValid(%s, %s, %s)", id, action, failures));
+               }
+
+               boolean valid = true;
+               if (action != Action.DELETE) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .isAnInternalError()
+                               .becauseOf("isValid(Long) is only supported for 
DELETE")
+                               .build());
+                       valid = false;
+               } else if (id == null) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("id")
+                               .isMissing()
+                               .build());
+                       valid = false;
+               } else if (getPolicy(id) == null) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("id")
+                               .isSemanticallyIncorrect()
+                               .becauseOf("no policy found for id[" + id + "]")
+                               .build());
+                       valid = false;
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValid(%s, %s, %s): %s", id, action, failures, valid));
+               }
+               return valid;
+       }
+
+       boolean isValid(RangerPolicy policy, Action action, 
List<ValidationFailureDetails> failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValid(%s, %s, %s)", policy, action, failures));
+               }
+
+               if (!(action == Action.CREATE || action == Action.UPDATE)) {
+                       throw new 
IllegalArgumentException("isValid(RangerPolicy, ...) is only supported for 
create/update");
+               }
+               boolean valid = true;
+               if (policy == null) {
+                       String message = "policy object passed in was null";
+                       LOG.debug(message);
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("policy")
+                               .isMissing()
+                               .becauseOf(message)
+                               .build());
+                       valid = false;
+               } else {
+                       Long id = policy.getId();
+                       if (action == Action.UPDATE) { // id is ignored for 
CREATE
+                               if (id == null) {
+                                       String message = "policy id was 
null/empty/blank"; 
+                                       LOG.debug(message);
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id")
+                                               .isMissing()
+                                               .becauseOf(message)
+                                               .build());
+                                       valid = false;
+                               } else if (getPolicy(id) == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("no policy exists 
with id[" + id +"]")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+                       String policyName = policy.getName();
+                       String serviceName = policy.getService();
+                       if (StringUtils.isBlank(policyName)) {
+                               String message = "policy name was 
null/empty/blank[" + policyName + "]"; 
+                               LOG.debug(message);
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("name")
+                                       .isMissing()
+                                       .becauseOf(message)
+                                       .build());
+                               valid = false;
+                       } else {
+                               List<RangerPolicy> policies = 
getPolicies(policyName, serviceName);
+                               if (CollectionUtils.isNotEmpty(policies)) {
+                                       if (policies.size() > 1) {
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .isAnInternalError()
+                                                       .becauseOf("multiple 
policies found with the name[" + policyName + "]")
+                                                       .build());
+                                               valid = false;
+                                       } else if (action == Action.CREATE) { 
// size == 1
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .field("name")
+                                                       
.isSemanticallyIncorrect()
+                                                       .becauseOf("policy 
already exists with name[" + policyName + "]; its id is[" + 
policies.iterator().next().getId() + "]")
+                                                       .build());
+                                               valid = false;
+                                       } else if 
(policies.iterator().next().getId() != id) { // size == 1 && action == UPDATE
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .field("id/name")
+                                                       
.isSemanticallyIncorrect()
+                                                       .becauseOf("id/name 
conflict: another policy already exists with name[" + policyName + "], its id 
is[" + policies.iterator().next().getId() + "]")
+                                                       .build());
+                                               valid = false;
+                                       }
+                               }
+                       }
+                       RangerService service = null;
+                       if (StringUtils.isBlank(serviceName)) {
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                               .field("service")
+                               .isMissing()
+                               .becauseOf("service name was null/empty/blank")
+                               .build());
+                               valid = false;
+                       } else {
+                               service = getService(serviceName);
+                               if (service == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("service")
+                                               .isMissing()
+                                               .becauseOf("service name was 
null/empty/blank")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+                       List<RangerPolicyItem> policyItems = 
policy.getPolicyItems();
+                       boolean isAuditEnabled = getIsAuditEnabled(policy);
+                       RangerServiceDef serviceDef = null;
+                       String serviceDefName = null;
+                       if (CollectionUtils.isEmpty(policyItems) && 
!isAuditEnabled) {
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("policy items")
+                                       .isMissing()
+                                       .becauseOf("at least one policy item 
must be specified if audit isn't enabled")
+                                       .build());
+                               valid = false;
+                       } else if (service != null) {
+                               serviceDefName = service.getType();
+                               serviceDef = getServiceDef(serviceDefName);
+                               if (serviceDef == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("policy service def")
+                                               .isAnInternalError()
+                                               .becauseOf("Service def of 
policies service does not exist")
+                                               .build());
+                                       valid = false;
+                               } else {
+                                       valid = isValidPolicyItems(policyItems, 
failures, serviceDef) && valid;
+                               }
+                       }
+                       if (serviceDef != null) {
+                               Set<String> mandatoryResources = 
getMandatoryResourceNames(serviceDef);
+                               Set<String> policyResources = 
getPolicyResources(policy);
+                               Set<String> missingResources = 
Sets.difference(mandatoryResources, policyResources);
+                               if (!missingResources.isEmpty()) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("resources")
+                                               
.subField(missingResources.iterator().next()) // we return any one parameter!
+                                               .isMissing()
+                                               .becauseOf("required 
resources[" + missingResources + "] are missing")
+                                               .build());
+                                       valid = false;
+                               }
+                               Set<String> allResource = 
getAllResourceNames(serviceDef);
+                               Set<String> unknownResources = 
Sets.difference(policyResources, allResource);
+                               if (!unknownResources.isEmpty()) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("resources")
+                                               
.subField(unknownResources.iterator().next()) // we return any one parameter!
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("resource[" + 
unknownResources + "] is not valid for service-def[" + serviceDefName + "]")
+                                               .build());
+                                       valid = false;
+                               }
+                               Map<String, RangerPolicyResource> resourceMap = 
policy.getResources();
+                               valid = isValidResourceValues(resourceMap, 
failures, serviceDef) && valid;
+                               valid = isValidResourceFlags(resourceMap, 
failures, serviceDef.getResources(), serviceDefName, policyName) && valid;
+                       }
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValid(%s, %s, %s): %s", policy, action, failures, 
valid));
+               }
+               return valid;
+       }
+       
+       boolean isValidResourceFlags(final Map<String, RangerPolicyResource> 
inputPolicyResources, final List<ValidationFailureDetails> failures,
+                       final List<RangerResourceDef> resourceDefs, final 
String serviceDefName, final String policyName) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s)", 
inputPolicyResources, failures, resourceDefs, serviceDefName, policyName));
+               }
+
+               boolean valid = true;
+               if (inputPolicyResources == null) {
+                       LOG.debug("isValidResourceFlags: resourceMap is null");
+               } else if (resourceDefs == null) {
+                       LOG.debug("isValidResourceFlags: service Def is null");
+               } else {
+                       Map<String, RangerPolicyResource> policyResources = 
getPolicyResourceWithLowerCaseKeys(inputPolicyResources);
+                       for (RangerResourceDef resourceDef : resourceDefs) {
+                               if (resourceDef == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("resource-def")
+                                               .isAnInternalError()
+                                               .becauseOf("a resource-def on 
resource def collection of service-def[" + serviceDefName + "] was null")
+                                               .build());
+                                       valid = false;
+                               } else if 
(StringUtils.isBlank(resourceDef.getName())) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("resource-def-name")
+                                               .isAnInternalError()
+                                               .becauseOf("name of a 
resource-def on resource def collection of service-def[" + serviceDefName + "] 
was null")
+                                               .build());
+                                       valid = false;
+                               } else {
+                                       String resourceName = 
resourceDef.getName().toLowerCase();
+                                       RangerPolicyResource policyResource = 
policyResources.get(resourceName);
+                                       if (policyResource == null) {
+                                               if (LOG.isDebugEnabled()) {
+                                                       LOG.debug("a 
policy-resource object for resource[" + resourceName + "] on policy [" + 
policyName + "] was null");
+                                               }
+                                       } else {
+                                               boolean excludesSupported = 
Boolean.TRUE.equals(resourceDef.getExcludesSupported()); // could be null
+                                               boolean policyIsExcludes = 
Boolean.TRUE.equals(policyResource.getIsExcludes()); // could be null
+                                               if (policyIsExcludes && 
!excludesSupported) {
+                                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                                               
.field("isExcludes")
+                                                               
.subField(resourceName)
+                                                               
.isSemanticallyIncorrect()
+                                                               
.becauseOf("isExcludes specified as [" + policyIsExcludes + "] for resource [" 
+ resourceName + "] which doesn't support isExcludes")
+                                                               .build());
+                                                       valid = false;
+                                               }
+                                               boolean recursiveSupported = 
Boolean.TRUE.equals(resourceDef.getRecursiveSupported());
+                                               boolean policyIsRecursive = 
Boolean.TRUE.equals(policyResource.getIsRecursive());
+                                               if (policyIsRecursive && 
!recursiveSupported) {
+                                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                                               
.field("isRecursive")
+                                                               
.subField(resourceName)
+                                                               
.isSemanticallyIncorrect()
+                                                               
.becauseOf("isRecursive specified as [" + policyIsRecursive + "] for resource 
[" + resourceName + "] which doesn't support isRecursive")
+                                                               .build());
+                                                       valid = false;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s): %s", 
inputPolicyResources, failures, resourceDefs, serviceDefName, policyName, 
valid));
+               }
+               return valid;
+       }
+
+       boolean isValidResourceValues(Map<String, RangerPolicyResource> 
resourceMap, List<ValidationFailureDetails> failures, RangerServiceDef 
serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValidResourceValues(%s, %s, %s)", resourceMap, 
failures, serviceDef));
+               }
+
+               boolean valid = true;
+               if (resourceMap == null) {
+                       LOG.debug("isValidResourceValues: resourceMap is null");
+               } else if (serviceDef == null) {
+                       LOG.debug("isValidResourceValues: service Def is null");
+               } else {
+                       Map<String, String> validationRegExMap = 
getValidationRegExes(serviceDef);
+                       for (Map.Entry<String, RangerPolicyResource> entry : 
resourceMap.entrySet()) {
+                               String name = entry.getKey();
+                               RangerPolicyResource policyResource = 
entry.getValue();
+                               if (validationRegExMap.containsKey(name) && 
policyResource != null && 
CollectionUtils.isNotEmpty(policyResource.getValues())) {
+                                       String regEx = 
validationRegExMap.get(name);
+                                       for (String aValue : 
policyResource.getValues()) {
+                                               if 
(StringUtils.isBlank(aValue)) {
+                                                       LOG.debug("resource 
value was blank");
+                                               } else if 
(!aValue.matches(regEx)) {
+                                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                                               
.field("resource-values")
+                                                               .subField(name)
+                                                               
.isSemanticallyIncorrect()
+                                                               
.becauseOf("resources value[" + aValue + "] does not match validation regex[" + 
regEx + "] defined on service-def[" + serviceDef.getName() + "]")
+                                                               .build());
+                                                       valid = false;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValidResourceValues(%s, %s, %s): %s", resourceMap, 
failures, serviceDef, valid));
+               }
+               return valid;
+       }
+
+       boolean isValidPolicyItems(List<RangerPolicyItem> policyItems, 
List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValid(%s, %s, %s)", policyItems, failures, serviceDef));
+               }
+
+               boolean valid = true;
+               if (CollectionUtils.isEmpty(policyItems)) {
+                       LOG.debug("policy items collection was null/empty");
+               } else {
+                       for (RangerPolicyItem policyItem : policyItems) {
+                               if (policyItem == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("policy item")
+                                               .isMissing()
+                                               .becauseOf("policy items object 
was null")
+                                               .build());
+                                       valid = false;
+                               } else {
+                                       // we want to go through all elements 
even though one may be bad so all failures are captured
+                                       valid = isValidPolicyItem(policyItem, 
failures, serviceDef) && valid;
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItems, failures, 
serviceDef, valid));
+               }
+               return valid;
+       }
+
+       boolean isValidPolicyItem(RangerPolicyItem policyItem, 
List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValid(%s, %s, %s)", policyItem, failures, serviceDef));
+               }
+               
+               boolean valid = true;
+               if (policyItem == null) {
+                       LOG.debug("policy item was null!");
+               } else {
+                       // access items collection can't be empty and should be 
otherwise valid
+                       if (CollectionUtils.isEmpty(policyItem.getAccesses())) {
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("policy item accesses")
+                                       .isMissing()
+                                       .becauseOf("policy items accesses 
collection was null")
+                                       .build());
+                               valid = false;
+                       } else {
+                               valid = 
isValidItemAccesses(policyItem.getAccesses(), failures, serviceDef) && valid;
+                       }
+                       // both users and user-groups collections can't be empty
+                       if (CollectionUtils.isEmpty(policyItem.getUsers()) && 
CollectionUtils.isEmpty(policyItem.getGroups())) {
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("policy item users/user-groups")
+                                       .isMissing()
+                                       .becauseOf("both users and user-groups 
collections on the policy item were null/empty")
+                                       .build());
+                               valid = false;
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItem, failures, 
serviceDef, valid));
+               }
+               return valid;
+       }
+
+       boolean isValidItemAccesses(List<RangerPolicyItemAccess> accesses, 
List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValid(%s, %s, %s)", accesses, failures, serviceDef));
+               }
+               
+               boolean valid = true;
+               if (CollectionUtils.isEmpty(accesses)) {
+                       LOG.debug("policy item accesses collection was 
null/empty!");
+               } else {
+                       Set<String> accessTypes = getAccessTypes(serviceDef);
+                       for (RangerPolicyItemAccess access : accesses) {
+                               if (access == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("policy item access")
+                                               .isMissing()
+                                               .becauseOf("policy items access 
object was null")
+                                               .build());
+                                       valid = false;
+                               } else {
+                                       // we want to go through all elements 
even though one may be bad so all failures are captured
+                                       valid = isValidPolicyItemAccess(access, 
failures, accessTypes) && valid;
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValid(%s, %s): %s", accesses, failures, serviceDef, 
valid));
+               }
+               return valid;
+       }
+
+       boolean isValidPolicyItemAccess(RangerPolicyItemAccess access, 
List<ValidationFailureDetails> failures, Set<String> accessTypes) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s)", access, failures, 
accessTypes));
+               }
+               
+               boolean valid = true;
+               if (CollectionUtils.isEmpty(accessTypes)) { // caller should 
firewall this argument!
+                       LOG.debug("isValidPolicyItemAccess: accessTypes was 
null!");
+               } else if (access == null) {
+                       LOG.debug("isValidPolicyItemAccess: policy item access 
was null!");
+               } else {
+                       String accessType = access.getType();
+                       if (StringUtils.isBlank(accessType)) {
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("policy item access type")
+                                       .isMissing()
+                                       .becauseOf("policy items access type's 
name was null/empty/blank")
+                                       .build());
+                               valid = false;
+                       } else if 
(!accessTypes.contains(accessType.toLowerCase())) {
+                               String message = String.format("access type[%s] 
not among valid types for service[%s]", accessType, accessTypes);
+                               LOG.debug(message);
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("policy item access type")
+                                       .isSemanticallyIncorrect()
+                                       .becauseOf(message)
+                                       .build());
+                               valid = false;
+                       }
+                       Boolean isAllowed = access.getIsAllowed();
+                       // it can be null (which is treated as allowed) but not 
false
+                       if (isAllowed != null && isAllowed == false) {
+                               String message = "access type is set to deny.  
Currently deny access types are not supported.";
+                               LOG.debug(message);
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("policy item access type 
allowed")
+                                       .isSemanticallyIncorrect()
+                                       .becauseOf(message)
+                                       .build());
+                               valid = false;
+                       }
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s): %s", access, 
failures, accessTypes, valid));
+               }
+               return valid;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
new file mode 100644
index 0000000..a870e28
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
@@ -0,0 +1,365 @@
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerServiceDefValidator extends RangerValidator {
+
+       private static final Log LOG = 
LogFactory.getLog(RangerServiceDefValidator.class);
+
+       public RangerServiceDefValidator(ServiceStore store) {
+               super(store);
+       }
+
+       public void validate(final RangerServiceDef serviceDef, final Action 
action) throws Exception {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerServiceDefValidator.validate(%s, %s)", serviceDef, action));
+               }
+
+               List<ValidationFailureDetails> failures = new 
ArrayList<ValidationFailureDetails>();
+               boolean valid = isValid(serviceDef, action, failures);
+               String message = "";
+               try {
+                       if (!valid) {
+                               message = serializeFailures(failures);
+                               throw new Exception(message);
+                       }
+               } finally {
+                       if(LOG.isDebugEnabled()) {
+                               LOG.debug(String.format("<== 
RangerServiceDefValidator.validate(%s, %s): %s, reason[%s]", serviceDef, 
action, valid, message));
+                       }
+               }
+       }
+
+       boolean isValid(final Long id, final Action action, final 
List<ValidationFailureDetails> failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerServiceDefValidator.isValid(" + id 
+ ")");
+               }
+
+               boolean valid = true;
+               if (action != Action.DELETE) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .isAnInternalError()
+                               .becauseOf("unsupported action[" + action + "]; 
isValid(Long) is only supported for DELETE")
+                               .build());
+                       valid = false;
+               } else if (id == null) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("id")
+                               .isMissing()
+                               .build());
+                       valid = false;
+               } else if (getServiceDef(id) == null) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("id")
+                               .isSemanticallyIncorrect()
+                               .becauseOf("no service def found for id[" + id 
+ "]")
+                               .build());
+                       valid = false;
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerServiceDefValidator.isValid(" + id 
+ "): " + valid);
+               }
+               return valid;
+       }
+       
+       boolean isValid(final RangerServiceDef serviceDef, final Action action, 
final List<ValidationFailureDetails> failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerServiceDefValidator.isValid(" + 
serviceDef + ")");
+               }
+               
+               if (!(action == Action.CREATE || action == Action.UPDATE)) {
+                       throw new 
IllegalArgumentException("isValid(RangerServiceDef, ...) is only supported for 
CREATE/UPDATE");
+               }
+               boolean valid = true;
+               if (serviceDef == null) {
+                       String message = "service def object passed in was 
null";
+                       LOG.debug(message);
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("service def")
+                               .isMissing()
+                               .becauseOf(message)
+                               .build());
+                       valid = false;
+               } else {
+                       Long id = serviceDef.getId();
+                       if (action == Action.UPDATE) { // id is ignored for 
CREATE
+                               if (id == null) {
+                                       String message = "service def id was 
null/empty/blank"; 
+                                       LOG.debug(message);
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id")
+                                               .isMissing()
+                                               .becauseOf(message)
+                                               .build());
+                                       valid = false;
+                               } else if (getServiceDef(id) == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("no service def 
exists with id[" + id +"]")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+                       // validate the service def name
+                       String name = serviceDef.getName();
+                       boolean nameSpecified = StringUtils.isNotBlank(name);
+                       if (!nameSpecified) {
+                               String message = "service def name[" + name + 
"] was null/empty/blank"; 
+                               LOG.debug(message);
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("name")
+                                       .isMissing()
+                                       .becauseOf(message)
+                                       .build());
+                               valid = false;
+                       } else {
+                               RangerServiceDef otherServiceDef = 
getServiceDef(name);
+                               if (otherServiceDef != null && action == 
Action.CREATE) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("name")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("service def with 
the name[" + name + "] already exists")
+                                               .build());
+                                       valid = false;
+                               } else if (otherServiceDef != null && 
otherServiceDef.getId() !=null && otherServiceDef.getId() != id) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id/name")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("id/name conflict: 
another service def already exists with name[" + name + "], its id is [" + 
otherServiceDef.getId() + "]")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+                       if 
(CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("access types")
+                                       .isMissing()
+                                       .becauseOf("access types collection was 
null/empty")
+                                       .build());
+                               valid = false;
+                       } else {
+                               valid = 
isValidAccessTypes(serviceDef.getAccessTypes(), failures) && valid;
+                       }
+                       if (CollectionUtils.isEmpty(serviceDef.getEnums())) {
+                               LOG.debug("No enums specified on the service 
def.  Ok!");
+                       } else {
+                               valid = isValidEnums(serviceDef.getEnums(), 
failures) && valid;
+                       }
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerServiceDefValidator.isValid(" + 
serviceDef + "): " + valid);
+               }
+               return valid;
+       }
+
+       boolean isValidAccessTypes(final List<RangerAccessTypeDef> 
accessTypeDefs, final List<ValidationFailureDetails> failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerServiceDefValidator.isValidAccessTypes(%s, %s)", accessTypeDefs, 
failures));
+               }
+               
+               boolean valid = true;
+               if (CollectionUtils.isEmpty(accessTypeDefs)) {
+                       LOG.debug("access type def collection is empty/null");
+               } else {
+                       List<RangerAccessTypeDef> defsWithImpliedGrants = new 
ArrayList<RangerAccessTypeDef>();
+                       Set<String> accessNames = new HashSet<String>();
+                       for (RangerAccessTypeDef def : accessTypeDefs) {
+                               String name = def.getName();
+                               // name can't be null/empty/blank
+                               if (StringUtils.isBlank(name)) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("access type name")
+                                               .isMissing()
+                                               .becauseOf("access type name[" 
+ name + "] is null/empty")
+                                               .build());
+                                       valid = false;
+                               } else if 
(accessNames.contains(name.toLowerCase())) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("access type name")
+                                               .subField(name)
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("duplicate access 
type names in access types collection: [" + name + "]")
+                                               .build());
+                                       valid = false;
+                               } else {
+                                       accessNames.add(name.toLowerCase()); // 
we have a new unique access type
+                               }
+                               if 
(CollectionUtils.isNotEmpty(def.getImpliedGrants())) {
+                                       defsWithImpliedGrants.add(def);
+                               }
+                       }
+                       // validate implied grants
+                       for (RangerAccessTypeDef def : defsWithImpliedGrants) {
+                               Collection<String> impliedGrants = 
getImpliedGrants(def);
+                               Set<String> unknownAccessTypes = 
Sets.difference(Sets.newHashSet(impliedGrants), accessNames);
+                               if (!unknownAccessTypes.isEmpty()) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("implied grants")
+                                               
.subField(unknownAccessTypes.iterator().next())  // we return just on item 
here.  Message has all unknow items
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("implied grant[" + 
impliedGrants + "] contains an unknown access types[" + unknownAccessTypes + 
"]")
+                                               .build());
+                                       valid = false;
+                               }
+                               // implied grant should not imply itself! 
+                               String name = def.getName(); // note: this name 
could be null/blank/empty!
+                               if (impliedGrants.contains(name)) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("implied grants")
+                                               .subField(name)
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("implied grants list 
[" + impliedGrants + "] for access type[" + name + "] contains itself")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerServiceDefValidator.isValidAccessTypes(%s, %s): %s", accessTypeDefs, 
failures, valid));
+               }
+               return valid;
+       }
+
+       boolean isValidEnums(List<RangerEnumDef> enumDefs, 
List<ValidationFailureDetails> failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerServiceDefValidator.isValidEnums(%s, %s)", enumDefs, failures));
+               }
+               
+               boolean valid = true;
+               if (CollectionUtils.isEmpty(enumDefs)) {
+                       LOG.debug("enum def collection passed in was 
null/empty");
+               } else {
+                       Set<String> enumNames = new HashSet<String>();
+                       for (RangerEnumDef enumDef : enumDefs) {
+                               if (enumDef == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("enum def")
+                                               .isMissing()
+                                               .becauseOf("An enum def in 
enums collection is null")
+                                               .build());
+                                       valid = false;
+                               } else {
+                                       // enum-names must non-blank and be 
unique to a service definition
+                                       String enumName = enumDef.getName();
+                                       if (StringUtils.isBlank(enumName)) {
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .field("enum def name")
+                                                       .isMissing()
+                                                       .becauseOf("enum name 
[" + enumName + "] is null/empty")
+                                                       .build());
+                                               valid = false;
+                                       } else if 
(enumNames.contains(enumName.toLowerCase())) {
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .field("enum def name")
+                                                       .subField(enumName)
+                                                       
.isSemanticallyIncorrect()
+                                                       .becauseOf("dumplicate 
enum name [" + enumName + "] found")
+                                                       .build());
+                                               valid = false;
+                                       } else {
+                                               
enumNames.add(enumName.toLowerCase());
+                                       }
+                                       // enum must contain at least one valid 
value and those values should be non-blank and distinct
+                                       if 
(CollectionUtils.isEmpty(enumDef.getElements())) {
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .field("enum values")
+                                                       .subField(enumName)
+                                                       .isMissing()
+                                                       .becauseOf("enum [" + 
enumName + "] does not have any elements")
+                                                       .build());
+                                               valid = false;
+                                       } else {
+                                               valid = 
isValidEnumElements(enumDef.getElements(), failures, enumName) && valid;
+                                               // default index should be valid
+                                               int defaultIndex = 
getEnumDefaultIndex(enumDef);
+                                               if (defaultIndex < 0 || 
defaultIndex >= enumDef.getElements().size()) { // max index is one less than 
the size of the elements list
+                                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                                               .field("enum 
default index")
+                                                               
.subField(enumName)
+                                                               
.isSemanticallyIncorrect()
+                                                               
.becauseOf("default index[" + defaultIndex + "] for enum [" + enumName + "] is 
invalid")
+                                                               .build());
+                                                       valid = false;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumDefs, failures, 
valid));
+               }
+               return valid;
+       }
+
+       boolean isValidEnumElements(List<RangerEnumElementDef> 
enumElementsDefs, List<ValidationFailureDetails> failures, String enumName) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerServiceDefValidator.isValidEnums(%s, %s)", enumElementsDefs, failures));
+               }
+               
+               boolean valid = true;
+               if (CollectionUtils.isEmpty(enumElementsDefs)) {
+                       LOG.debug("Enum elements list passed in was 
null/empty!");
+               } else {
+                       // enum element names should be valid and distinct
+                       Set<String> elementNames = new HashSet<String>();
+                       for (RangerEnumElementDef elementDef : 
enumElementsDefs) {
+                               if (elementDef == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("enum element")
+                                               .subField(enumName)
+                                               .isMissing()
+                                               .becauseOf("An enum element in 
enum element collection of enum [" + enumName + "] is null")
+                                               .build());
+                                       valid = false;
+                               } else {
+                                       String elementName = 
elementDef.getName();
+                                       if (StringUtils.isBlank(elementName)) {
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .field("enum element 
name")
+                                                       .subField(enumName)
+                                                       .isMissing()
+                                                       .becauseOf("Name of an 
element of enum [" + enumName + "] is null/empty[" + elementName + "]")
+                                                       .build());
+                                               valid = false;
+                                       } else if 
(elementNames.contains(elementName.toLowerCase())) {
+                                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                                       .field("enum element 
name")
+                                                       .subField(enumName)
+                                                       
.isSemanticallyIncorrect()
+                                                       .becauseOf("dumplicate 
enum element name [" + elementName + "] found for enum[" + enumName + "]")
+                                                       .build());
+                                               valid = false;
+                                       } else {
+                                               
elementNames.add(elementName.toLowerCase());
+                                       }
+                               }
+                       }
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("<== 
RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumElementsDefs, 
failures, valid));
+               }
+               return valid;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
new file mode 100644
index 0000000..2019284
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerServiceValidator extends RangerValidator {
+
+       private static final Log LOG = 
LogFactory.getLog(RangerServiceValidator.class);
+
+       public RangerServiceValidator(ServiceStore store) {
+               super(store);
+       }
+
+       public void validate(RangerService service, Action action) throws 
Exception {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug(String.format("==> 
RangerServiceValidator.validate(%s, %s)", service, action));
+               }
+
+               List<ValidationFailureDetails> failures = new 
ArrayList<ValidationFailureDetails>();
+               boolean valid = isValid(service, action, failures);
+               String message = "";
+               try {
+                       if (!valid) {
+                               message = serializeFailures(failures);
+                               throw new Exception(message);
+                       }
+               } finally {
+                       if(LOG.isDebugEnabled()) {
+                               LOG.debug(String.format("<== 
RangerServiceValidator.validate(%s, %s): %s, reason[%s]", service, action, 
valid, message));
+                       }
+               }
+       }
+       
+       boolean isValid(Long id, Action action, List<ValidationFailureDetails> 
failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerServiceValidator.isValid(" + id + 
")");
+               }
+
+               boolean valid = true;
+               if (action != Action.DELETE) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .isAnInternalError()
+                               .becauseOf("unsupported action[" + action + "]; 
isValid(Long) is only supported for DELETE")
+                               .build());
+                       valid = false;
+               } else if (id == null) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("id")
+                               .isMissing()
+                               .build());
+                       valid = false;
+               } else if (getService(id) == null) {
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("id")
+                               .isSemanticallyIncorrect()
+                               .becauseOf("no service found for id[" + id + 
"]")
+                               .build());
+                       valid = false;
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerServiceValidator.isValid(" + id + 
"): " + valid);
+               }
+               return valid;
+       }
+       
+       boolean isValid(RangerService service, Action action, 
List<ValidationFailureDetails> failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerServiceValidator.isValid(" + 
service + ")");
+               }
+               if (!(action == Action.CREATE || action == Action.UPDATE)) {
+                       throw new 
IllegalArgumentException("isValid(RangerService, ...) is only supported for 
CREATE/UPDATE");
+               }
+               
+               boolean valid = true;
+               if (service == null) {
+                       String message = "service object passed in was null";
+                       LOG.debug(message);
+                       failures.add(new ValidationFailureDetailsBuilder()
+                               .field("service")
+                               .isMissing()
+                               .becauseOf(message)
+                               .build());
+                       valid = false;
+               } else {
+                       Long id = service.getId();
+                       if (action == Action.UPDATE) { // id is ignored for 
CREATE
+                               if (id == null) {
+                                       String message = "service id was 
null/empty/blank"; 
+                                       LOG.debug(message);
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id")
+                                               .isMissing()
+                                               .becauseOf(message)
+                                               .build());
+                                       valid = false;
+                               } else if (getService(id) == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("no service exists 
with id[" + id +"]")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+                       String name = service.getName();
+                       boolean nameSpecified = StringUtils.isNotBlank(name);
+                       RangerServiceDef serviceDef = null;
+                       if (!nameSpecified) {
+                               String message = "service name[" + name + "] 
was null/empty/blank"; 
+                               LOG.debug(message);
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("name")
+                                       .isMissing()
+                                       .becauseOf(message)
+                                       .build());
+                               valid = false;
+                       } else {
+                               RangerService otherService = getService(name);
+                               if (otherService != null && action == 
Action.CREATE) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("name")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("service with the 
name[" + name + "] already exists")
+                                               .build());
+                                       valid = false;
+                               } else if (otherService != null && 
otherService.getId() !=null && otherService.getId() != id) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("id/name")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("id/name conflict: 
another service already exists with name[" + name + "], its id is [" + 
otherService.getId() + "]")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+                       String type = service.getType();
+                       boolean typeSpecified = StringUtils.isNotBlank(type);
+                       if (!typeSpecified) {
+                               failures.add(new 
ValidationFailureDetailsBuilder()
+                                       .field("type")
+                                       .isMissing()
+                                       .becauseOf("service def [" + type + "] 
was null/empty/blank")
+                                       .build());
+                               valid = false;
+                       } else {
+                               serviceDef = getServiceDef(type);
+                               if (serviceDef == null) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("type")
+                                               .isSemanticallyIncorrect()
+                                               .becauseOf("service def named[" 
+ type + "] not found")
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+                       if (nameSpecified && serviceDef != null) {
+                               // check if required parameters were specified
+                               Set<String> reqiredParameters = 
getRequiredParameters(serviceDef);
+                               Set<String> inputParameters = 
getServiceConfigParameters(service);
+                               Set<String> missingParameters = 
Sets.difference(reqiredParameters, inputParameters);
+                               if (!missingParameters.isEmpty()) {
+                                       failures.add(new 
ValidationFailureDetailsBuilder()
+                                               .field("configuration")
+                                               
.subField(missingParameters.iterator().next()) // we return any one parameter!
+                                               .isMissing()
+                                               .becauseOf("required 
configuration parameter is missing; missing parameters: " + missingParameters)
+                                               .build());
+                                       valid = false;
+                               }
+                       }
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerServiceValidator.isValid(" + 
service + "): " + valid);
+               }
+               return valid;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
new file mode 100644
index 0000000..7bf744e
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
@@ -0,0 +1,480 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model.validation;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
+
+public abstract class RangerValidator {
+       
+       private static final Log LOG = LogFactory.getLog(RangerValidator.class);
+
+       ServiceStore _store;
+
+       public enum Action {
+               CREATE, UPDATE, DELETE;
+       };
+       
+       protected RangerValidator(ServiceStore store) {
+               if (store == null) {
+                       throw new IllegalArgumentException("ServiceValidator(): 
store is null!");
+               }
+               _store = store;
+       }
+
+       public void validate(Long id, Action action) throws Exception {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.validate(" + id + ")");
+               }
+
+               List<ValidationFailureDetails> failures = new 
ArrayList<ValidationFailureDetails>();
+               if (isValid(id, action, failures)) {
+                       if(LOG.isDebugEnabled()) {
+                               LOG.debug("<== RangerValidator.validate(" + id 
+ "): valid");
+                       }
+               } else {
+                       String message = serializeFailures(failures);
+                       LOG.debug("<== RangerValidator.validate(" + id + "): 
invalid, reason[" + message + "]");
+                       throw new Exception(message);
+               }
+       }
+       
+       /**
+        * This method is expected to be overridden by sub-classes.  Default 
implementation provided to not burden implementers from having to implement 
methods that they know would never be called. 
+        * @param id
+        * @param action
+        * @param failures
+        * @return
+        */
+       boolean isValid(Long id, Action action, List<ValidationFailureDetails> 
failures) {
+               failures.add(new ValidationFailureDetailsBuilder()
+                               .isAnInternalError()
+                               .becauseOf("unimplemented method called")
+                               .build());
+               return false;
+       }
+
+       String serializeFailures(List<ValidationFailureDetails> failures) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getFailureMessage()");
+               }
+
+               String message = null;
+               if (CollectionUtils.isEmpty(failures)) {
+                       LOG.warn("serializeFailures: called while list of 
failures is null/empty!");
+               } else {
+                       StringBuilder builder = new StringBuilder();
+                       for (ValidationFailureDetails aFailure : failures) {
+                               builder.append(aFailure.toString());
+                               builder.append(";");
+                       }
+                       message = builder.toString();
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.serializeFailures(): " + 
message);
+               }
+               return message;
+       }
+
+       Set<String> getServiceConfigParameters(RangerService service) {
+               if (service == null || service.getConfigs() == null) {
+                       return new HashSet<String>();
+               } else {
+                       return service.getConfigs().keySet();
+               }
+       }
+
+       Set<String> getRequiredParameters(RangerServiceDef serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getRequiredParameters(" 
+ serviceDef + ")");
+               }
+
+               Set<String> result;
+               if (serviceDef == null) {
+                       result = Collections.emptySet();
+               } else {
+                       List<RangerServiceConfigDef> configs = 
serviceDef.getConfigs();
+                       if (CollectionUtils.isEmpty(configs)) {
+                               result = Collections.emptySet();
+                       } else {
+                               result = new HashSet<String>(configs.size()); 
// at worse all of the config items are required!
+                               for (RangerServiceConfigDef configDef : 
configs) {
+                                       if (configDef.getMandatory()) {
+                                               result.add(configDef.getName());
+                                       }
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getRequiredParameters(" 
+ serviceDef + "): " + result);
+               }
+               return result;
+       }
+
+       RangerServiceDef getServiceDef(Long id) {
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getServiceDef(" + id + 
")");
+               }
+               RangerServiceDef result = null;
+               try {
+                       result = _store.getServiceDef(id);
+               } catch (Exception e) {
+                       LOG.debug("Encountred exception while retrieving 
service def from service store!", e);
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getServiceDef(" + id + 
"): " + result);
+               }
+               return result;
+       }
+
+       RangerServiceDef getServiceDef(String type) {
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getServiceDef(" + type + 
")");
+               }
+               RangerServiceDef result = null;
+               try {
+                       result = _store.getServiceDefByName(type);
+               } catch (Exception e) {
+                       LOG.debug("Encountred exception while retrieving 
service definition from service store!", e);
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getServiceDef(" + type + 
"): " + result);
+               }
+               return result;
+       }
+
+       RangerService getService(Long id) {
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getService(" + id + ")");
+               }
+               RangerService result = null;
+               try {
+                       result = _store.getService(id);
+               } catch (Exception e) {
+                       LOG.debug("Encountred exception while retrieving 
service from service store!", e);
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getService(" + id + "): 
" + result);
+               }
+               return result;
+       }
+
+       RangerService getService(String name) {
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getService(" + name + 
")");
+               }
+               RangerService result = null;
+               try {
+                       result = _store.getServiceByName(name);
+               } catch (Exception e) {
+                       LOG.debug("Encountred exception while retrieving 
service from service store!", e);
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getService(" + name + 
"): " + result);
+               }
+               return result;
+       }
+
+       RangerPolicy getPolicy(Long id) {
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getPolicy(" + id + ")");
+               }
+               RangerPolicy result = null;
+               try {
+                       result = _store.getPolicy(id);
+               } catch (Exception e) {
+                       LOG.debug("Encountred exception while retrieving policy 
from service store!", e);
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getPolicy(" + id + "): " 
+ result);
+               }
+               return result;
+       }
+
+       List<RangerPolicy> getPolicies(final String policyName, final String 
serviceName) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getPolicies(" + 
policyName + ", " + serviceName + ")");
+               }
+
+               List<RangerPolicy> policies = null;
+               try {
+                       SearchFilter filter = new SearchFilter();
+                       filter.setParam(SearchFilter.POLICY_NAME, policyName);
+                       filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+                       
+                       policies = _store.getPolicies(filter);
+               } catch (Exception e) {
+                       LOG.debug("Encountred exception while retrieving 
service from service store!", e);
+               }
+               
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getPolicies(" + 
policyName + ", " + serviceName + "): " + policies);
+               }
+               return policies;
+       }
+
+       Set<String> getAccessTypes(RangerServiceDef serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getAccessTypes(" + 
serviceDef + ")");
+               }
+
+               Set<String> accessTypes = new HashSet<String>();
+               if (serviceDef == null) {
+                       LOG.warn("serviceDef passed in was null!");
+               } else if 
(CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+                       LOG.warn("AccessTypeDef collection on serviceDef was 
null!");
+               } else {
+                       for (RangerAccessTypeDef accessTypeDef : 
serviceDef.getAccessTypes()) {
+                               if (accessTypeDef == null) {
+                                       LOG.warn("Access type def was null!");
+                               } else {
+                                       String accessType = 
accessTypeDef.getName();
+                                       if (StringUtils.isBlank(accessType)) {
+                                               LOG.warn("Access type def name 
was null/empty/blank!");
+                                       } else {
+                                               
accessTypes.add(accessType.toLowerCase());
+                                       }
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getAccessTypes(" + 
serviceDef + "): " + accessTypes);
+               }
+               return accessTypes;
+       }
+       
+       /**
+        * This function exists to encapsulates the current behavior of code 
which treats and unspecified audit preference to mean audit is enabled.
+        * @param policy
+        * @return
+        */
+       boolean getIsAuditEnabled(RangerPolicy policy) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getIsAuditEnabled(" + 
policy + ")");
+               }
+
+               boolean isEnabled = false;
+               if (policy == null) {
+                       LOG.warn("policy was null!");
+               } else if (policy.getIsAuditEnabled() == null) {
+                       isEnabled = true;
+               } else {
+                       isEnabled = policy.getIsAuditEnabled();
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getIsAuditEnabled(" + 
policy + "): " + isEnabled);
+               }
+               return isEnabled;
+       }
+       
+       /**
+        * Returns names of resource types set to lower-case to allow for 
case-insensitive comparison. 
+        * @param serviceDef
+        * @return
+        */
+       Set<String> getMandatoryResourceNames(RangerServiceDef serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerValidator.getMandatoryResourceNames(" + serviceDef + ")");
+               }
+
+               Set<String> resourceNames = new HashSet<String>();
+               if (serviceDef == null) {
+                       LOG.warn("serviceDef passed in was null!");
+               } else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
+                       LOG.warn("ResourceDef collection on serviceDef was 
null!");
+               } else {
+                       for (RangerResourceDef resourceTypeDef : 
serviceDef.getResources()) {
+                               if (resourceTypeDef == null) {
+                                       LOG.warn("resource type def was null!");
+                               } else {
+                                       Boolean mandatory = 
resourceTypeDef.getMandatory();
+                                       if (mandatory != null && mandatory == 
true) {
+                                               String resourceName = 
resourceTypeDef.getName();
+                                               if 
(StringUtils.isBlank(resourceName)) {
+                                                       LOG.warn("Resource def 
name was null/empty/blank!");
+                                               } else {
+                                                       
resourceNames.add(resourceName.toLowerCase());
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerValidator.getMandatoryResourceNames(" + serviceDef + "): " + 
resourceNames);
+               }
+               return resourceNames;
+       }
+
+       Set<String> getAllResourceNames(RangerServiceDef serviceDef) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerValidator.getAllResourceNames(" + 
serviceDef + ")");
+               }
+
+               Set<String> resourceNames = new HashSet<String>();
+               if (serviceDef == null) {
+                       LOG.warn("serviceDef passed in was null!");
+               } else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
+                       LOG.warn("ResourceDef collection on serviceDef was 
null!");
+               } else {
+                       for (RangerResourceDef resourceTypeDef : 
serviceDef.getResources()) {
+                               if (resourceTypeDef == null) {
+                                       LOG.warn("resource type def was null!");
+                               } else {
+                                       String resourceName = 
resourceTypeDef.getName();
+                                       if (StringUtils.isBlank(resourceName)) {
+                                               LOG.warn("Resource def name was 
null/empty/blank!");
+                                       } else {
+                                               
resourceNames.add(resourceName.toLowerCase());
+                                       }
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerValidator.getAllResourceNames(" + 
serviceDef + "): " + resourceNames);
+               }
+               return resourceNames;
+       }
+       
+       /**
+        * Returns the resource-types defined on the policy converted to 
lowe-case
+        * @param policy
+        * @return
+        */
+       Set<String> getPolicyResources(RangerPolicy policy) {
+               if (policy == null || policy.getResources() == null || 
policy.getResources().isEmpty()) {
+                       return new HashSet<String>();
+               } else {
+                       Set<String> result = new HashSet<String>();
+                       for (String name : policy.getResources().keySet()) {
+                               result.add(name.toLowerCase());
+                       }
+                       return result;
+               }
+       }
+
+       Map<String, String> getValidationRegExes(RangerServiceDef serviceDef) {
+               if (serviceDef == null || 
CollectionUtils.isEmpty(serviceDef.getResources())) {
+                       return new HashMap<String, String>();
+               } else {
+                       Map<String, String> result = new HashMap<String, 
String>();
+                       for (RangerResourceDef resourceDef : 
serviceDef.getResources()) {
+                               if (resourceDef == null) {
+                                       LOG.warn("A resource def in resource 
def collection is null");
+                               } else {
+                                       String name = resourceDef.getName();
+                                       String regEx = 
resourceDef.getValidationRegEx();
+                                       if (StringUtils.isBlank(name)) {
+                                               LOG.warn("resource name is 
null/empty/blank");
+                                       } else if (StringUtils.isBlank(regEx)) {
+                                               LOG.debug("validation regex is 
null/empty/blank");
+                                       } else {
+                                               result.put(name, regEx);
+                                       }
+                               }
+                       }
+                       return result;
+               }
+       }
+       
+       int getEnumDefaultIndex(RangerEnumDef enumDef) {
+               int index;
+               if (enumDef == null) {
+                       index = -1;
+               } else if (enumDef.getDefaultIndex() == null) {
+                       index = 0;
+               } else {
+                       index = enumDef.getDefaultIndex();
+               }
+               return index;
+       }
+
+       Collection<String> getImpliedGrants(RangerAccessTypeDef def) {
+               if (def == null) {
+                       return null;
+               } else if (CollectionUtils.isEmpty(def.getImpliedGrants())) {
+                       return new ArrayList<String>();
+               } else {
+                       List<String> result = new 
ArrayList<String>(def.getImpliedGrants().size());
+                       for (String name : def.getImpliedGrants()) {
+                               if (StringUtils.isBlank(name)) {
+                                       result.add(name); // could be null!
+                               } else {
+                                       result.add(name.toLowerCase());
+                               }
+                       }
+                       return result;
+               }
+       }
+
+       /**
+        * Returns a copy of the policy resource map where all keys 
(resource-names) are lowercase
+        * @param input
+        * @return
+        */
+       Map<String, RangerPolicyResource> 
getPolicyResourceWithLowerCaseKeys(Map<String, RangerPolicyResource> input) {
+               if (input == null) {
+                       return null;
+               }
+               Map<String, RangerPolicyResource> output = new HashMap<String, 
RangerPolicyResource>(input.size());
+               for (Map.Entry<String, RangerPolicyResource> entry : 
input.entrySet()) {
+                       output.put(entry.getKey().toLowerCase(), 
entry.getValue());
+               }
+               return output;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
new file mode 100644
index 0000000..f72e8df
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model.validation;
+
+import org.apache.ranger.plugin.store.ServiceStore;
+
+public class RangerValidatorFactory {
+       public RangerServiceValidator getServiceValidator(ServiceStore store) {
+               return new RangerServiceValidator(store);
+       }
+
+       public RangerPolicyValidator getPolicyValidator(ServiceStore store) {
+               return new RangerPolicyValidator(store);
+       }
+
+       public RangerServiceDefValidator getServiceDefValidator(ServiceStore 
store) {
+               return new RangerServiceDefValidator(store);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
new file mode 100644
index 0000000..015203a
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.Objects;
+
+public class ValidationFailureDetails {
+
+       final String _fieldName;
+       final String _subFieldName;
+       final boolean _missing;
+       final boolean _semanticError;
+       final boolean _internalError;
+       final String _reason;
+       
+       public ValidationFailureDetails(String fieldName, String subFieldName, 
boolean missing, boolean semanticError, boolean internalError, String reason) {
+               _missing = missing;
+               _semanticError = semanticError;
+               _internalError = internalError;
+               _fieldName = fieldName;
+               _subFieldName = subFieldName;
+               _reason = reason;
+       }
+
+       public String getFieldName() {
+               return _fieldName;
+       }
+
+       public boolean isMissingRequiredValue() {
+               return _missing;
+       }
+
+       public boolean isSemanticallyIncorrect() {
+               return _semanticError;
+       }
+       
+       String getType() {
+               if (_missing) return "missing";
+               if (_semanticError) return "semantically incorrect";
+               if (_internalError) return "internal error";
+               return "";
+       }
+
+       public String getSubFieldName() {
+               return _subFieldName;
+       }
+       
+       @Override
+       public String toString() {
+               return String.format("Field[%s]%s is %s: reason[%s]", 
+                               _fieldName, 
+                               _subFieldName == null ? "" : ", subField[" + 
_subFieldName + "]",
+                               getType(), _reason);
+       }
+       
+       @Override
+       public int hashCode() {
+               return Objects.hash(_fieldName, _subFieldName, _missing, 
_semanticError, _internalError, _reason);
+       }
+       
+       @Override
+       public boolean equals(Object obj) {
+               if (obj == null || !(obj instanceof ValidationFailureDetails)) {
+                       return false;
+               }
+               ValidationFailureDetails that = (ValidationFailureDetails)obj;
+               return Objects.equals(_fieldName, that._fieldName) && 
+                               Objects.equals(_subFieldName, 
that._subFieldName) && 
+                               Objects.equals(_reason, that._reason) && 
+                               _internalError == that._internalError &&
+                               _missing == that._missing &&
+                               _semanticError == that._semanticError;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
new file mode 100644
index 0000000..3a57341
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model.validation;
+
+public class ValidationFailureDetailsBuilder {
+       private String _fieldName;
+       private boolean _missing;
+       private boolean _semanticError;
+       private String _reason;
+       private String _subFieldName;
+       private boolean _internalError;
+       
+       ValidationFailureDetailsBuilder becauseOf(String aReason) {
+               _reason = aReason;
+               return this;
+       }
+       
+       ValidationFailureDetailsBuilder isMissing() {
+               _missing = true;
+               return this;
+       }
+       
+       ValidationFailureDetailsBuilder isSemanticallyIncorrect() {
+               _semanticError = true;
+               return this;
+       }
+       
+       ValidationFailureDetailsBuilder field(String fieldName) {
+               _fieldName = fieldName;
+               return this;
+       }
+       
+       ValidationFailureDetails build() {
+               return new ValidationFailureDetails(_fieldName, _subFieldName, 
_missing, _semanticError, _internalError, _reason);
+       }
+
+       ValidationFailureDetailsBuilder subField(String missingParameter) {
+               _subFieldName = missingParameter;
+               return this;
+       }
+
+       ValidationFailureDetailsBuilder isAnInternalError() {
+               _internalError = true;
+               return this;
+       }
+
+}

Reply via email to