/* * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.jcr.impl.core.value; import org.exoplatform.services.jcr.impl.util.JCRDateFormat; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import javax.jcr.PropertyType; import javax.jcr.ValueFormatException; import javax.jcr.nodetype.ConstraintViolationException; /** * Created by The eXo Platform SAS. * * @author <a href="mailto:peter.nedonosko@exoplatform.com">Peter Nedonosko</a> * @version $Id: ValueConstraintsValidator.java 12171 2008-03-20 15:37:28Z ksm $ */ public class ValueConstraintsValidator { protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.ValueConstraintsValidator"); protected final static String DEFAULT_THRESHOLD = ""; protected final String[] constraints; public ValueConstraintsValidator(String[] constraints) { this.constraints = constraints; } protected MinMaxConstraint parseAsMinMax(String constraint) throws ConstraintViolationException { // constraint as min,max range: // value constraints in the form of inclusive or exclusive ranges: // i.e., "[min, max]", "(min, max)", "(min, max]" or "[min, max)". // Where "[" and "]" indicate "inclusive", while "(" and ")" indicate // "exclusive". // A missing min or max value indicates no bound in that direction String[] parts = constraint.split(","); if (parts.length != 2) { throw new ConstraintViolationException("Value constraint '" + constraint + "' is invalid accrding the JSR-170 spec."); } boolean exclusive = false; if (parts[0].startsWith("(")) { exclusive = true; } else if (parts[0].startsWith("[")) { exclusive = false; } else { throw new ConstraintViolationException("Value constraint '" + constraint + "' min exclusion rule is unefined accrding the JSR-170 spec."); } ConstraintRange minValue = new ConstraintRange(parts[0].length() > 1 ? parts[0].substring(1) : DEFAULT_THRESHOLD, exclusive); if (parts[1].endsWith(")")) { exclusive = true; } else if (parts[1].endsWith("]")) { exclusive = false; } else { throw new ConstraintViolationException("Value constraint '" + constraint + "' max exclusion rule is unefined accrding the JSR-170 spec."); } ConstraintRange maxValue = new ConstraintRange(parts[1].length() > 1 ? parts[1].substring(0, parts[1].length() - 1) : DEFAULT_THRESHOLD, exclusive); return new MinMaxConstraint(minValue, maxValue); } /** * Validate this matcher constraints for a validity to a given type. * * @param type int, property type * @throws ValueFormatException if the constraint (at least one) incompatible with the given type */ public void validateFor(final int type) throws ValueFormatException { if (constraints == null || constraints.length <= 0) { return; } if (type == PropertyType.DATE) { for (String constrString : constraints) { try { MinMaxConstraint constraint = parseAsMinMax(constrString); if (constraint.getMin().getThreshold().length() > 0) { JCRDateFormat.parse(constraint.getMin().getThreshold()); } if (constraint.getMax().getThreshold().length() > 0) { JCRDateFormat.parse(constraint.getMax().getThreshold()); } } catch (ValueFormatException e) { throw new ValueFormatException("Wrong DATE constraint format " + constrString, e); } catch (ConstraintViolationException e) { throw new ValueFormatException("Wrong DATE constraint format " + constrString, e); } } } else if (type == PropertyType.DOUBLE) { for (String constrString : constraints) { try { MinMaxConstraint constraint = parseAsMinMax(constrString); if (constraint.getMin().getThreshold().length() > 0) { Double.parseDouble(constraint.getMin().getThreshold()); } if (constraint.getMax().getThreshold().length() > 0) { Double.parseDouble(constraint.getMax().getThreshold()); } } catch (NumberFormatException e) { throw new ValueFormatException("Wrong DOUBLE constraint format " + constrString, e); } catch (ConstraintViolationException e) { throw new ValueFormatException("Wrong DOUBLE constraint format " + constrString, e); } } } else if (type == PropertyType.LONG || type == PropertyType.BINARY) { for (String constrString : constraints) { try { MinMaxConstraint constraint = parseAsMinMax(constrString); if (constraint.getMin().getThreshold().length() > 0) { Long.parseLong(constraint.getMin().getThreshold()); } if (constraint.getMax().getThreshold().length() > 0) { Long.parseLong(constraint.getMax().getThreshold()); } } catch (NumberFormatException e) { throw new ValueFormatException("Wrong LONG (or BINARY size) constraint format " + constrString, e); } catch (ConstraintViolationException e) { throw new ValueFormatException("Wrong LONG (or BINARY size) constraint format " + constrString, e); } } } else if (type == PropertyType.BOOLEAN) { for (String constrString : constraints) { if (!constrString.equalsIgnoreCase("true") && !constrString.equalsIgnoreCase("false")) { throw new ValueFormatException("Wrong BOOLEAN constraint format: " + constrString); } } } } protected class ConstraintRange { private final String value; private final boolean exclusive; public ConstraintRange(String value) { this.value = value; this.exclusive = false; } public ConstraintRange(String value, boolean exclusive) { this.value = value; this.exclusive = exclusive; } protected String getThreshold() { return value; } protected boolean isExclusive() { return exclusive; } } protected class MinMaxConstraint { private final ConstraintRange minValue; private final ConstraintRange maxValue; public MinMaxConstraint(ConstraintRange minValue, ConstraintRange maxValue) { this.minValue = minValue; this.maxValue = maxValue; } protected ConstraintRange getMax() { return maxValue; } protected ConstraintRange getMin() { return minValue; } } }