001/* Copyright (C) 2014 konik.io
002 *
003 * This file is part of the Konik library.
004 *
005 * The Konik library is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * The Konik library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with the Konik library. If not, see <http://www.gnu.org/licenses/>.
017 */
018package io.konik.validation;
019
020import java.util.Set;
021
022import javax.inject.Inject;
023import javax.inject.Named;
024import javax.inject.Singleton;
025import javax.validation.ConstraintViolation;
026import javax.validation.Validation;
027import javax.validation.Validator;
028import javax.validation.ValidatorFactory;
029import javax.validation.groups.Default;
030
031import org.apache.bval.jsr.DefaultMessageInterpolator;
032
033import io.konik.validator.annotation.Comfort;
034import io.konik.validator.annotation.Extended;
035import io.konik.zugferd.Invoice;
036import io.konik.zugferd.profile.ConformanceLevel;
037
038/**
039 * Validates the invoice against the declared invoice profile.
040 */
041@Named
042@Singleton
043public class InvoiceValidator {
044
045   private final Validator validator;
046   private final MonetarySummationValidator monetarySummationValidator;
047
048   /**
049    * Instantiates a new invoice validator.
050    *
051    * @param validator the validator
052    * @param monetarySummationValidator 
053    */
054   @Inject
055   public InvoiceValidator(Validator validator, MonetarySummationValidator monetarySummationValidator) {
056      super();
057      this.validator = validator;
058      this.monetarySummationValidator = monetarySummationValidator;
059   }
060
061   /**
062    * Instantiates a new invoice validator.
063    *
064    * @param validator the validator
065    */
066   public InvoiceValidator(Validator validator) {
067      super();
068      this.validator = validator;
069      this.monetarySummationValidator = new MonetarySummationValidator(new DefaultMessageInterpolator());
070   }
071
072   /**
073    * Instantiates a new default invoice validator, based on the Bean Validation provider
074    */
075   public InvoiceValidator() {
076      ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
077      this.validator = factory.getValidator();
078      this.monetarySummationValidator = new MonetarySummationValidator(new DefaultMessageInterpolator());
079   }
080
081   /**
082    * Validate the invoice
083    *
084    * @param invoice the invoice
085    * @return the sets the
086    */
087   public Set<ConstraintViolation<Invoice>> validate(Invoice invoice) {
088      ConformanceLevel conformanceLevel = invoice.getContext().getGuideline().getConformanceLevel();
089      Class<?>[] validationGroups = resolveIntoValidationGroups(conformanceLevel);
090      Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice, validationGroups);
091      if (monetarySummationValidator != null) {
092         violations.addAll(monetarySummationValidator.validate(invoice, validationGroups));
093      }
094      return violations;
095   }
096
097   /**
098    * Resolve the given profile into bean validation groups.
099    *
100    * @param conformanceLevel the given profile
101    * @return the class[] list of validation group classes
102    */
103   public static Class<?>[] resolveIntoValidationGroups(ConformanceLevel conformanceLevel) {
104      switch (conformanceLevel) {
105      case BASIC:
106         return new Class[] { Default.class };
107      case COMFORT:
108         return new Class[] { Default.class, Comfort.class };
109      case EXTENDED:
110         return new Class[] { Default.class, Comfort.class, Extended.class };
111      default:
112         throw new IllegalArgumentException("Provided Profile:" + conformanceLevel + "not covered");
113      }
114   }
115}