package annis.rest.provider;

import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

import org.corpus_tools.graphannis.errors.AQLSyntaxError;
import org.corpus_tools.graphannis.errors.GraphANNISException;

import annis.model.AqlParseError;
import annis.model.ParsedEntityLocation;

public abstract class AQLErrorMapperBase<T extends GraphANNISException> implements ExceptionMapper<T> {

    private static final Pattern locationPattern = Pattern.compile(
                "\\[(?<startline>[0-9]+):(?<startcol>[0-9]+)(-(?<endline>[0-9]+):(?<endcol>[0-9]+))?\\]");

    public AQLErrorMapperBase() {
        super();
    }

    @Override
    public Response toResponse(T exception) {
     
        List<AqlParseError> errors = new LinkedList<>();
        String[] errorMessageBlocks = exception.getMessage().split("---+\n");
        
        for(String block : errorMessageBlocks) {
            
            String[] msgLines = block.split("\n");
            
            AqlParseError e = new AqlParseError();
            if(msgLines.length > 0) {
                StringBuilder sb = new StringBuilder(msgLines[0]);
                // append the hints as well
                for(int i=2; i < msgLines.length; i++) {
                    sb.append("\n");
                    sb.append(msgLines[i]);
                }
                e.setMessage(sb.toString());
            }
            
            if(msgLines.length > 1) {
               // get the position information
               Matcher m = locationPattern.matcher(msgLines[1]);
               if(m.matches()) {
                   ParsedEntityLocation loc = new ParsedEntityLocation();
                   String startLine = m.group("startline");
                   String startCol = m.group("startcol");
                   String endLine = m.group("endline");
                   String endCol = m.group("endcol");
                   
                   loc.setStartLine(Integer.parseInt(startLine));
                   loc.setStartColumn(Integer.parseInt(startCol));
                   
                   if(endLine != null &&  endCol != null) {
                       loc.setEndLine(Integer.parseInt(endLine));
                       loc.setEndColumn(Integer.parseInt(endCol));
                   } else {
                       loc.setEndLine(loc.getStartLine());
                       loc.setEndColumn(loc.getStartColumn());
                   }
                   e.setLocation(loc);
               }
            }
            errors.add(e);
        }
    
        return Response.status(Response.Status.BAD_REQUEST)
                .entity(new GenericEntity<List<AqlParseError>>(errors) {
                }).type("application/xml").build();
    }

}
@@ -728,20 +728,39 @@
 %5D+))?%5C%5C%5D
-%22);%0A
+( (?%3Cmsg%3E.+))?%22);%0A%0A    
 %0A    pub
@@ -808,16 +808,21 @@
 );%0A    %7D
+%0A    
 %0A%0A    @O
@@ -1218,37 +1218,9 @@
     
-if(msgLines.length %3E 0) %7B%0A   
+%0A
     
@@ -1223,25 +1223,24 @@
             
- 
 StringBuilde
@@ -1241,18 +1241,19 @@
 Builder 
-sb
+msg
  = new S
@@ -1269,19 +1269,8 @@
 der(
-msgLines%5B0%5D
 );%0A 
@@ -1284,43 +1284,9 @@
     
-    // append the hints as well%0A   
+%0A
     
@@ -1289,25 +1289,24 @@
             
- 
 for(int i=2;
@@ -1307,9 +1307,9 @@
 t i=
-2
+0
 ; i 
@@ -1354,242 +1354,66 @@
     
-    
-sb.append(%22%5Cn%22);%0A                    sb.append(msgLines%5Bi%5D);%0A                %7D%0A                e.setMessage(sb.toString());%0A            %7D%0A            %0A            if(msgLines.length %3E 1) %7B%0A               // get the position inform
+if(i == 0) %7B%0A                    // check for optional loc
 atio
@@ -1429,16 +1429,21 @@
         
+ 
+    
 Matcher 
@@ -1483,9 +1483,9 @@
 nes%5B
-1
+i
 %5D);%0A
@@ -1499,16 +1499,21 @@
         
+ 
+    
 if(m.mat
@@ -1541,16 +1541,21 @@
         
+   
+  
 ParsedEn
@@ -1597,24 +1597,29 @@
 Location();%0A
+     
             
@@ -1677,32 +1677,37 @@
                 
+     
 String startCol 
@@ -1740,32 +1740,37 @@
                 
+  
+   
 String endLine =
@@ -1801,32 +1801,37 @@
                 
+     
 String endCol = 
@@ -1860,32 +1860,37 @@
                 
+     
 %0A               
@@ -1885,32 +1885,37 @@
                 
+     
 loc.setStartLine
@@ -1937,32 +1937,37 @@
 nt(startLine));%0A
+     
                 
@@ -2028,33 +2028,43 @@
                 
+    
-%0A
+ %0A     
                 
@@ -2122,32 +2122,37 @@
                 
+     
 loc.setEndLine(I
@@ -2193,32 +2193,37 @@
                 
+   
+  
 loc.setEndColumn
@@ -2246,24 +2246,29 @@
 t(endCol));%0A
+     
             
@@ -2298,32 +2298,37 @@
                 
+     
 loc.setEndLine(l
@@ -2362,32 +2362,37 @@
                 
+  
+   
 loc.setEndColumn
@@ -2426,34 +2426,44 @@
                 
-%7D%0A
+     %7D%0A     
                 
@@ -2504,23 +2504,523 @@
     
-%7D%0A            %7D
+         %0A                        String msgPart = m.group(%22msg%22);%0A                        if(msgPart != null) %7B%0A                            msg.append(msgPart);%0A                        %7D%0A                    %7D%0A                %7D else %7B%0A                    // append whole line%0A                    msg.append(msgLines%5Bi%5D);%0A                %7D%0A                if(i %3C msgLines.length-1) %7B%0A                    msg.append('%5Cn');%0A                %7D%0A            %7D // end for each line%0A            e.setMessage(msg.toString());
 %0A   

Adapt to new (simpler) format of the error messsages