package org.datacite.mds.validation.constraints.impl;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.datacite.mds.domain.Allocator;
import org.datacite.mds.domain.Datacentre;
import org.datacite.mds.util.ValidationUtils;
import org.datacite.mds.validation.constraints.Symbol;
import org.datacite.mds.validation.constraints.Symbol.Type;

public class SymbolValidator implements ConstraintValidator<Symbol, String> {

    List<Type> types;
    boolean hasToExist;
    
    static final HashMap<Type, Pattern> PATTERNS = new HashMap<Type, Pattern>() {
        {
            String symbol = "[A-Z][A-Z\\-]{0,6}[A-Z]"; 
            put(Type.ALLOCATOR, Pattern.compile(symbol));
            put(Type.DATACENTRE, Pattern.compile(symbol + "\\." + symbol));
        }
    };
    
    public void initialize(Symbol constraintAnnotation) {
        types = Arrays.asList(constraintAnnotation.value());
        hasToExist = constraintAnnotation.hasToExist();
    }

    public boolean isValid(String symbol, ConstraintValidatorContext context) {
        // TODO check if required
        context.disableDefaultConstraintViolation();
        if (symbol == null) {
            return true;
        }
        if (hasToExist) {
            // do database lookup only
            return exists(symbol, context);
        } else {
            return !isMalformed(symbol, context);
        }
    }

    boolean isMalformed(String symbol, ConstraintValidatorContext context) {
        for (Type t : types) {
            if (PATTERNS.get(t).matcher(symbol).matches() && symbol.indexOf("--") == -1) {
                //check against the pattern for each given type 
                return false;
            } else {
                String message = "{org.datacite.mds.validation.constraints.Symbol." + t.name() + ".message}";
                ValidationUtils.addConstraintViolation(context, message);
            }
        }
        return true;
    }

    boolean exists(String symbol, ConstraintValidatorContext context) {
        //check table Allocator or Datacentre based on given types
        if (types.contains(Type.ALLOCATOR)) {
            if (Allocator.findAllocatorBySymbol(symbol) != null) {
                return true;
            }
        }
        
        if (types.contains(Type.DATACENTRE)) {
            if (Datacentre.findDatacentreBySymbol(symbol) != null) {
                return true;
            }
        }

        ValidationUtils.addConstraintViolation(context, "{org.datacite.mds.validation.constraints.Symbol.notfound}");
        return false;
    }
}

@@ -281,67 +281,24 @@
 mds.
-domain.Allocator;%0Aimport org.datacite.mds.domain.Datacentre
+util.DomainUtils
 ;%0Aim
@@ -1260,33 +1260,32 @@
 symbol == null) 
-%7B
 %0A            ret
@@ -1294,33 +1294,32 @@
 n true;%0A        
-%7D
 %0A        if (has
@@ -1319,60 +1319,97 @@
 if (
-hasToExist) %7B%0A            // do database lookup only
+isMalformed(symbol, context))%0A            return false;%0A        %0A        if (hasToExist) 
 %0A   
@@ -1453,32 +1453,24 @@
 t);%0A        
-%7D else %7B
 %0A           
@@ -1470,59 +1470,20 @@
     
-    
 return 
-!isMalformed(symbol, context);%0A        %7D
+true;
 %0A   
@@ -2121,138 +2121,41 @@
     
-//check table Allocator or Datacentre based on given types%0A        if (types.contains(Type.ALLOCATOR)) %7B%0A            if (Allocator
+boolean foundSymbol = DomainUtils
 .fin
@@ -2164,16 +2164,28 @@
 llocator
+OrDatacentre
 BySymbol
@@ -2204,242 +2204,60 @@
 null
-) %7B%0A                return true;%0A            %7D%0A        %7D%0A        %0A        if (types.contains(Type.DATACENTRE)) %7B%0A            if (Datacentre.findDatacentreBySymbol(symbol) != null) %7B%0A                return true;%0A            %7D%0A        %7D
+;%0A        if (foundSymbol) %0A            return true;
 %0A%0A  

simplify SymbolValidator