class RangerPolicyValidator extends RangerValidator {

	boolean isValidResourceFlags(final Map<String, RangerPolicyResource> inputPolicyResources, final List<ValidationFailureDetails> failures,
			final List<RangerResourceDef> resourceDefs, final String serviceDefName, final String policyName, boolean isAdmin) {
		if(LOG.isDebugEnabled()) {
			LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s, %s)", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName, isAdmin));
		}

		boolean valid = true;
		if (resourceDefs == null) {
			LOG.debug("isValidResourceFlags: service Def is null");
		} else {
			Map<String, RangerPolicyResource> policyResources = getPolicyResourceWithLowerCaseKeys(inputPolicyResources);
			for (RangerResourceDef resourceDef : resourceDefs) {
				if (resourceDef == null) {
					ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_NULL_RESOURCE_DEF;
					failures.add(new ValidationFailureDetailsBuilder()
						.field("resource-def")
						.isAnInternalError()
						.becauseOf(error.getMessage(serviceDefName))
						.errorCode(error.getErrorCode())
						.build());
					valid = false;
				} else if (StringUtils.isBlank(resourceDef.getName())) {
					ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_RESOURCE_DEF_NAME;
					failures.add(new ValidationFailureDetailsBuilder()
						.field("resource-def-name")
						.isAnInternalError()
						.becauseOf(error.getMessage(serviceDefName))
						.errorCode(error.getErrorCode())
						.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 policyResourceIsExcludes = Boolean.TRUE.equals(policyResource.getIsExcludes()); // could be null
						if (policyResourceIsExcludes && !excludesSupported) {
							ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_EXCLUDES_NOT_SUPPORTED;
							failures.add(new ValidationFailureDetailsBuilder()
								.field("isExcludes")
								.subField(resourceName)
								.isSemanticallyIncorrect()
								.becauseOf(error.getMessage(resourceName))
								.errorCode(error.getErrorCode())
								.build());
							valid = false;
						}
						if (policyResourceIsExcludes && !isAdmin) {
							ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_EXCLUDES_REQUIRES_ADMIN;
							failures.add(new ValidationFailureDetailsBuilder()
								.field("isExcludes")
								.subField("isAdmin")
								.isSemanticallyIncorrect()
								.becauseOf(error.getMessage())
								.errorCode(error.getErrorCode())
								.build());
							valid = false;
						}
						boolean recursiveSupported = Boolean.TRUE.equals(resourceDef.getRecursiveSupported());
						boolean policyIsRecursive = Boolean.TRUE.equals(policyResource.getIsRecursive());
						if (policyIsRecursive && !recursiveSupported) {
							ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_RECURSIVE_NOT_SUPPORTED;
							failures.add(new ValidationFailureDetailsBuilder()
								.field("isRecursive")
								.subField(resourceName)
								.isSemanticallyIncorrect()
								.becauseOf(error.getMessage(resourceName))
								.errorCode(error.getErrorCode())
								.build());
							valid = false;
						}
					}
				}
			}
		}

		if(LOG.isDebugEnabled()) {
			LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s, %s): %s", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName, isAdmin, valid));
		}
		return valid;
	}

	public  RangerPolicyValidator(ServiceStore store);

}