<commit_before>package es.weso.shex.validator

import cats.implicits._
import com.typesafe.scalalogging.LazyLogging
import es.weso.rdf.PREFIXES._
import es.weso.rdf.nodes._
import es.weso.shex.ViolationError._
import es.weso.shex._
import es.weso.shex.validator.ShExChecker._
import es.weso.utils.RegEx

case class FacetChecker(schema: Schema)
  extends ShowValidator(schema) with LazyLogging {

  def checkFacets(
    attempt: Attempt,
    node: RDFNode)(facets: List[XsFacet]): CheckTyping = for {
    ts <- checkAll(facets.map(checkFacet(attempt, node)(_)))
    t <- combineTypings(ts)
  } yield t

  def length(node: RDFNode): Int = node.getLexicalForm.length

  def checkFacet(
    attempt: Attempt,
    node: RDFNode)(facet: XsFacet): CheckTyping = {
    logger.info(s"checkFacet: ${node.show} ${facet}")
    facet match {
      case Length(n) => {
        val l = length(node)
        checkCond(
          l == n,
          attempt,
          msgErr(s"${node.show} does not satisfy facet Length($n) with length $l"),
          s"${node.show} satisfies Length($n) with length $l")
      }
      case MinLength(n) => {
        val l = length(node)
        checkCond(
          length(node) >= n,
          attempt,
          msgErr(s"${node.show} does not satisfy facet MinLength($n) with length $l"),
          s"${node.show} satisfies MinLength($n) with length $l")
      }
      case MaxLength(n) => {
        val l = length(node)
        checkCond(
          length(node) <= n,
          attempt,
          msgErr(s"${node.show} does not satisfy facet MaxLength($n) with length $l"),
          s"${node.show} satisfies MaxLength($n) with length $l")
      }
      case Pattern(p, flags) => {
        val str = node.getLexicalForm
        RegEx(p, flags).matches(str) match {
          case Right(b) => checkCond(b, attempt,
            msgErr(s"${node.show} does not match Pattern($p) with lexical form $str"),
            s"${node.show} satisfies Pattern($p) with lexical form $str")
          case Left(msg) => errStr(msg)
        }
      }
      case MinInclusive(m) => for {
        d <- minInclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MinInclusive($m) with $node"),
          s"${node.show} satisfies MinInclusive($m)")
      } yield r
      case MinExclusive(m) => for {
        d <- minExclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MinExclusive($m) with $node"),
          s"${node.show} satisfies MinExclusive($m)")
      } yield r
      case MaxInclusive(m) => for {
        d <- maxInclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MaxInclusive($m) with $node"),
          s"${node.show} satisfies MaxInclusive($m)")
      } yield r
      case MaxExclusive(m) => for {
        d <- maxExclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MaxExclusive($m) with $node"),
          s"${node.show} satisfies MaxExclusive($m)")
      } yield r

      case _ => {
        logger.error(s"Not implemented checkFacet: $facet")<commit_msg>First attempt to implement totalDigits<commit_after>package es.weso.shex.validator
import org.apache.xerces.impl.dv.xs.DecimalDV
import cats.implicits._
import com.typesafe.scalalogging.LazyLogging
import es.weso.rdf.PREFIXES._
import es.weso.rdf.nodes._
import es.weso.shex.ViolationError._
import es.weso.shex._
import es.weso.shex.validator.ShExChecker._
import es.weso.utils.RegEx
import org.apache.xerces.impl.dv.{SchemaDVFactory, ValidatedInfo, XSSimpleType}
import org.apache.xerces.impl.validation.ValidationState

case class FacetChecker(schema: Schema)
  extends ShowValidator(schema) with LazyLogging {

  def checkFacets(
    attempt: Attempt,
    node: RDFNode)(facets: List[XsFacet]): CheckTyping = for {
    ts <- checkAll(facets.map(checkFacet(attempt, node)(_)))
    t <- combineTypings(ts)
  } yield t

  def length(node: RDFNode): Int = node.getLexicalForm.length

  def totalDigits(node: RDFNode): Check[Int] = node match {
    case DecimalLiteral(d) => {
      val context = new ValidationState
      val validatedInfo = new ValidatedInfo
      val decimalDV = new DecimalDV()
      val typeDeclaration : XSSimpleType = SchemaDVFactory.getInstance.getBuiltInType("decimal")
      val xsdValue = validatedInfo.actualValue;
      val resultInfo = new ValidatedInfo
      typeDeclaration.validate(node.getLexicalForm,context,resultInfo)
      ok(decimalDV.getTotalDigits(resultInfo))
    }
    case DoubleLiteral(d) => {
      errStr(s"Not implemented yet totalDigits of doubleLiteral")
    }
    case _ => errStr(s"Not implemented yet")
  }

  def fractionDigits(node: RDFNode): Check[Int] =
    errStr(s"Unimplemented fraction digits of $node")

  def checkFacet(
    attempt: Attempt,
    node: RDFNode)(facet: XsFacet): CheckTyping = {
    logger.info(s"checkFacet: ${node.show} ${facet}")
    facet match {
      case Length(n) => {
        val l = length(node)
        checkCond(
          l == n,
          attempt,
          msgErr(s"${node.show} does not satisfy facet Length($n) with length $l"),
          s"${node.show} satisfies Length($n) with length $l")
      }
      case MinLength(n) => {
        val l = length(node)
        checkCond(
          length(node) >= n,
          attempt,
          msgErr(s"${node.show} does not satisfy facet MinLength($n) with length $l"),
          s"${node.show} satisfies MinLength($n) with length $l")
      }
      case MaxLength(n) => {
        val l = length(node)
        checkCond(
          length(node) <= n,
          attempt,
          msgErr(s"${node.show} does not satisfy facet MaxLength($n) with length $l"),
          s"${node.show} satisfies MaxLength($n) with length $l")
      }
      case Pattern(p, flags) => {
        val str = node.getLexicalForm
        RegEx(p, flags).matches(str) match {
          case Right(b) => checkCond(b, attempt,
            msgErr(s"${node.show} does not match Pattern($p) with lexical form $str"),
            s"${node.show} satisfies Pattern($p) with lexical form $str")
          case Left(msg) => errStr(msg)
        }
      }
      case MinInclusive(m) => for {
        d <- minInclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MinInclusive($m) with $node"),
          s"${node.show} satisfies MinInclusive($m)")
      } yield r
      case MinExclusive(m) => for {
        d <- minExclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MinExclusive($m) with $node"),
          s"${node.show} satisfies MinExclusive($m)")
      } yield r
      case MaxInclusive(m) => for {
        d <- maxInclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MaxInclusive($m) with $node"),
          s"${node.show} satisfies MaxInclusive($m)")
      } yield r
      case MaxExclusive(m) => for {
        d <- maxExclusive(m, node)
        r <- checkCond(d, attempt, msgErr(s"${node.show} does not match MaxExclusive($m) with $node"),
          s"${node.show} satisfies MaxExclusive($m)")
      } yield r
      case FractionDigits(m) => for {
        fd <- fractionDigits(node)
        r <- checkCond(fd <= m, attempt, msgErr(s"${node.show} does not match FractionDigits($m) with $node and fraction digits = $fd"),
          s"${node.show} satisfies FractionDigits($m) with fraction digits = $fd")
      } yield r
      case TotalDigits(m) => for {
        td <- totalDigits(node)
        r <- checkCond(td <= m, attempt, msgErr(s"${node.show} does not match TotalDigits($m) with $node and totalDigits = $td"),
          s"${node.show} satisfies TotalDigits($m) with total digits = $td")
      } yield r
      case _ => {
        logger.error(s"Not implemented checkFacet: $facet")
{'fraction_non_alphanumeric': 0.13537006263581747, 'fraction_numerical': 0.0, 'mean_word_length': 2.7417503586800573, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4628034', 'n_tokens_mistral': 2587, 'n_tokens_neox': 2541, 'n_words': 628}