/*
 * Copyright (c) 2013-2014 Josef Hardi <josef.hardi@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.obidea.semantika.materializer;

import static java.lang.String.format;

import java.net.URISyntaxException;

import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.ValueFactoryImpl;

import com.obidea.semantika.datatype.DataType;
import com.obidea.semantika.util.TemplateStringHelper;

/* package */class SesameStatement implements Statement
{
   private static final long serialVersionUID = 629451L;

   private ValueFactory mValueFactory = ValueFactoryImpl.getInstance();

   private String mSubjectValue;
   private String mPredicateValue;
   private String mObjectValue;

   private TriplesProjection mProjection;

   public SesameStatement(TriplesProjection projection, String subjectValue, String predicateValue, String objectValue)
   {
      mSubjectValue = subjectValue;
      mPredicateValue = predicateValue;
      mObjectValue = objectValue;
      mProjection = projection;
   }

   @Override
   public Resource getContext()
   {
      return null;
   }

   @Override
   public Resource getSubject()
   {
      int category = mProjection.getDataCategory(1);
      switch (category) {
         case TriplesProjection.DATA_URI:
            return mValueFactory.createURI(getUriString(mSubjectValue));
         case TriplesProjection.DATA_LITERAL:
            throw new TriplesStatementException("Subject cannot be literal"); //$NON-NLS-1$
         default:
            throw new TriplesStatementException(format("Illegal data category (%s)", category)); //$NON-NLS-1$
      }
   }

   @Override
   public URI getPredicate()
   {
      int category = mProjection.getDataCategory(2);
      switch (category) {
         case TriplesProjection.DATA_URI:
            return mValueFactory.createURI(mPredicateValue);
         case TriplesProjection.DATA_LITERAL:
            throw new TriplesStatementException("Predicate cannot be literal"); //$NON-NLS-1$
         default:
            throw new TriplesStatementException(format("Illegal data category (%s)", category)); //$NON-NLS-1$
      }
   }

   @Override
   public Value getObject()
   {
      int category = mProjection.getDataCategory(3);
      switch (category) {
         case TriplesProjection.DATA_URI:
            return mValueFactory.createURI(getUriString(mObjectValue));
         case TriplesProjection.DATA_LITERAL:
            String datatype = mProjection.getDatatype(3);
            return (datatype.equals(DataType.STRING)) ?
               mValueFactory.createLiteral(mObjectValue) : // use syntactic sugar for xsd:string
               mValueFactory.createLiteral(mObjectValue, mValueFactory.createURI(datatype));
      }
      throw new TriplesStatementException("Unknown data category [" + category + "]"); //$NON-NLS-1$ //$NON-NLS-2$
   }

   private String getUriString(String value)
   {
      String uriString = value;
      
      /*
       * Check if the given object value is a URI-template string or a URI string.
       */
      if (!validUri(uriString)) {
         /*
          * If it is a URI template string then reconstruct it to be a URI string.
          */
         uriString = TemplateStringHelper.buildUri(value);
      }
      return uriString;
   }

   /*
    * A utility method to check if the given URI string is a valid URI construction.
    * This method is used exclusively to check if the given value is in the form of
    * a URI template string or an already URI string.
    */
   private static boolean validUri(String uriString)
   {
      try {
         new java.net.URI(uriString);
      }
      catch (URISyntaxException e) {
         return false;
      }
      return true;
   }
}

@@ -1001,24 +1001,146 @@
 atatype.
-DataType
+AbstractXmlType;%0Aimport com.obidea.semantika.datatype.XmlDataTypeProfile;%0Aimport com.obidea.semantika.datatype.primitive.XsdString
 ;%0Aimport
@@ -3208,26 +3208,92 @@
     
-S
 tr
-ing datatype = 
+y %7B%0A               AbstractXmlType%3C?%3E xmlType = XmlDataTypeProfile.getXmlDatatype(
 mPro
@@ -3314,16 +3314,17 @@
 atype(3)
+)
 ;%0A      
@@ -3333,52 +3333,117 @@
     
-return (datatype.equals(DataType.STRING)) ?%0A
+   Object value = xmlType.getValue(mObjectValue);%0A               return (xmlType instanceof XsdString) ?%0A    
     
@@ -3445,32 +3445,34 @@
                 
+  
 mValueFactory.cr
@@ -3483,29 +3483,38 @@
 Literal(
-mObjectV
+String.valueOf(v
 alue)
+)
  : // us
@@ -3534,24 +3534,15 @@
 ugar
- for xsd:string%0A
+%0A      
     
@@ -3584,66 +3584,234 @@
 ral(
-mObjectValue, mValueFactory.createURI(datatype));%0A      %7D%0A
+String.valueOf(value), xmlType.getName());%0A            %7D%0A            catch (Exception e) %7B%0A               throw new TriplesStatementException(%22Failed to create literal%22, e); //$NON-NLS-1$%0A            %7D%0A         default:%0A      
     
@@ -3852,16 +3852,23 @@
 ion(
-%22Unknown
+format(%22Illegal
  dat
@@ -3882,12 +3882,14 @@
 ory 
-%5B%22 +
+(%25s)%22,
  cat
@@ -3897,14 +3897,9 @@
 gory
- + %22%5D%22
+)
 ); /
@@ -3914,22 +3914,16 @@
 S-1$
- //$NON-NLS-2$
+%0A      %7D
 %0A   

Use AbstractXmlType to handle the proper lexical reprentation of values for each XML datatype.