001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.repository.query.expression;
017
018import org.ametys.plugins.repository.RepositoryConstants;
019
020/**
021 * Constructs an {@link Expression} corresponding to the String comparison with a metadata of type MULTILANGUAL.
022 */
023public class MultilingualStringExpression implements Expression
024{
025    private String _value;
026    private MetadataExpression _metadata;
027    private Operator _operator;
028    private boolean _caseInsensitive; 
029    private String _lang;
030    
031    /**
032     * Creates the comparison Expression.
033     * @param metadata the metadata name
034     * @param operator the operator to make the comparison
035     * @param value the String value
036     * @param lang the language code
037     */
038    public MultilingualStringExpression(String metadata, Operator operator, String value, String lang)
039    {
040        _value = value;
041        _operator = operator;
042        _metadata = new MetadataExpression(metadata);
043        _caseInsensitive = false;
044        _lang = lang;
045
046    }
047    
048    /**
049     * Creates the comparison Expression.
050     * @param metadata the metadata name
051     * @param operator the operator to make the comparison
052     * @param value the String value
053     * @param lang the language code
054     * @param unversioned true if the metadata is unversioned, false otherwise.
055     */
056    public MultilingualStringExpression(String metadata, Operator operator, String value, String lang, boolean unversioned)
057    {
058        _value = value;
059        _operator = operator;
060        _metadata = new MetadataExpression(metadata, unversioned);
061        _caseInsensitive = false;
062        _lang = lang;
063    }
064    
065    /**
066     * Creates the comparison Expression.
067     * @param metadata the metadata name
068     * @param operator the operator to make the comparison
069     * @param value the String value
070     * @param lang the language code
071     * @param unversioned true if the metadata is unversioned, false otherwise.
072     * @param caseInsensitive <code>true</code> if the search must be case insensitive.
073     */
074    public MultilingualStringExpression(String metadata, Operator operator, String value, String lang, boolean unversioned, boolean caseInsensitive)
075    {
076        _value = value;
077        _operator = operator;
078        _metadata = new MetadataExpression(metadata, unversioned);
079        _caseInsensitive = caseInsensitive;
080        _lang = lang;
081    }
082    
083    public String build()
084    {
085        if (_operator.equals(Operator.WD))
086        {
087            if (_caseInsensitive)
088            {
089                return "jcr:like(fn:lower-case(" + _multilingualPath() + "), '%" + _escapeValue(_value.toLowerCase()) + "%')";
090            }
091            else
092            {
093                return "jcr:like(" + _multilingualPath() + ", '%" + _escapeValue(_value) + "%')";
094            }
095        }
096        else
097        {
098            if (_caseInsensitive)
099            {
100                return "fn:lower-case(" + _multilingualPath() + ") " + _operator + " '" + _value.toLowerCase().replaceAll("'", "''") + "'";
101            }
102            else
103            {
104                return _multilingualPath()  + " " + _operator + " '" + _value.replaceAll("'", "''") + "'";
105            }
106        }
107    }
108
109    private String _escapeValue(String value)
110    {
111        // First escape ' - " \ _ and %, Then escape ' into '' for XQuery compliance
112        return value.replaceAll("(['\\-_\"\\\\%])", "\\\\$1").replaceAll("'", "''");
113    }
114    
115    private String _multilingualPath()
116    {
117        return _metadata.build() + "/" + RepositoryConstants.NAMESPACE_PREFIX + ":" +  _lang;
118    }
119}