/*
 *
 * Copyright (c) 2006 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "qpid/acl/AclValidator.h"
#include "qpid/acl/AclData.h"
#include "qpid/Exception.h"
#include "qpid/log/Statement.h"
#include "qpid/sys/IntegerTypes.h"
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <numeric>
#include <sstream>

namespace qpid {
namespace acl {

AclValidator::IntPropertyType::IntPropertyType(int64_t i,int64_t j) : min(i), max(j){    
}

bool AclValidator::IntPropertyType::validate(const std::string& val) {
  int64_t v;
  try
  {
    v = boost::lexical_cast<int64_t>(val);
  }catch(const boost::bad_lexical_cast&){
    return 0;
  }

  if (v < min || v >= max){
    return 0;
  }else{
    return 1;
  }
}

std::string AclValidator::IntPropertyType::allowedValues() {
   return "values should be between " + 
          boost::lexical_cast<std::string>(min) + " and " +
          boost::lexical_cast<std::string>(max);
}

AclValidator::EnumPropertyType::EnumPropertyType(std::vector<std::string>& allowed): values(allowed){      
}

bool AclValidator::EnumPropertyType::validate(const std::string& val) {
  for (std::vector<std::string>::iterator itr = values.begin(); itr != values.end(); ++itr ){
     if (val.compare(*itr) == 0){
        return 1;
     }
  }

  return 0;
}

std::string AclValidator::EnumPropertyType::allowedValues() {
   std::ostringstream oss;
   oss << "possible values are one of { ";
   for (std::vector<std::string>::iterator itr = values.begin(); itr != values.end(); itr++ ){
        oss << "'" << *itr << "' ";
   }
   oss << "}";
   return oss.str();
}

AclValidator::AclValidator(){
  validators.insert(Validator(acl::PROP_MAXQUEUESIZE,
                              boost::shared_ptr<PropertyType>(
                                new IntPropertyType(0,std::numeric_limits<int64_t>::max()))
                             )
                   );

  validators.insert(Validator(acl::PROP_MAXQUEUECOUNT,
                              boost::shared_ptr<PropertyType>(
                                new IntPropertyType(0,std::numeric_limits<int64_t>::max()))
                             )
                   );

  std::string policyTypes[] = {"ring", "ring_strict", "flow_to_disk", "reject"};
  std::vector<std::string> v(policyTypes, policyTypes + sizeof(policyTypes) / sizeof(std::string));
  validators.insert(Validator(acl::PROP_POLICYTYPE,
                              boost::shared_ptr<PropertyType>(new EnumPropertyType(v))
                             )
                   );
  
}

AclValidator::~AclValidator(){
}

/* Iterate through the data model and validate the parameters. */
void AclValidator::validate(boost::shared_ptr<AclData> d) {
  
    for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++){

        if (d->actionList[cnt]){

	        for (unsigned int cnt1=0; cnt1< qpid::acl::OBJECTSIZE; cnt1++){

		        if (d->actionList[cnt][cnt1]){

                    std::for_each(d->actionList[cnt][cnt1]->begin(),
                                  d->actionList[cnt][cnt1]->end(),
                                  boost::bind(&AclValidator::validateRuleSet, this, _1));                    
                }//if 
            }//for
	    }//if
	}//for
}

void AclValidator::validateRuleSet(std::pair<const std::string, qpid::acl::AclData::ruleSet>& rules){
    std::for_each(rules.second.begin(),
                  rules.second.end(),
                  boost::bind(&AclValidator::validateRule, this, _1)); 
}

void AclValidator::validateRule(qpid::acl::AclData::rule& rule){
    std::for_each(rule.props.begin(),
                  rule.props.end(),
                  boost::bind(&AclValidator::validateProperty, this, _1)); 
}

void AclValidator::validateProperty(std::pair<const qpid::acl::Property, std::string>& prop){
   ValidatorItr itr = validators.find(prop.first);
    if (itr != validators.end()){
        QPID_LOG(debug,"Found validator for property " << itr->second->allowedValues());

        if (!itr->second->validate(prop.second)){
            throw Exception( prop.second + " is not a valid value for '" + 
                             AclHelper::getPropertyStr(prop.first) + "', " +
                             itr->second->allowedValues());
        } 
    }
}

}}
