001/*
002 *  Copyright 2011 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.glossary;
017
018import org.apache.commons.lang.StringUtils;
019
020import org.ametys.plugins.repository.AmetysRepositoryException;
021import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
022import org.ametys.plugins.repository.query.expression.Expression;
023import org.ametys.web.repository.site.Site;
024
025/**
026 * Glossary helper.
027 */
028public final class GlossaryHelper
029{
030    
031    /** The glossary page tag. */
032    public static final String GLOSSARY_PAGE_TAG = "GLOSSARY";
033    
034    private static final String __PLUGIN_NODE_NAME = "glossary";
035    
036    private static final String __DEFINITIONS_NODE_NAME = "ametys:wordDefinitions";
037    
038    private GlossaryHelper()
039    {
040        // Hides the default constructor.
041    }
042    
043    /**
044     * Get the root plugin storage object.
045     * @param site the site.
046     * @return the root plugin storage object.
047     * @throws AmetysRepositoryException if a repository error occurs.
048     */
049    public static ModifiableTraversableAmetysObject getPluginNode(Site site) throws AmetysRepositoryException
050    {
051        try
052        {
053            ModifiableTraversableAmetysObject pluginsNode = site.getRootPlugins();
054            
055            return getOrCreateNode(pluginsNode, __PLUGIN_NODE_NAME, "ametys:unstructured");
056        }
057        catch (AmetysRepositoryException e)
058        {
059            throw new AmetysRepositoryException("Error getting the glossary plugin node for site " + site.getName(), e);
060        }
061    }
062    
063    /**
064     * Get the word definitions storage node.
065     * @param site the site
066     * @param language the language.
067     * @return the word definitions storage node.
068     * @throws AmetysRepositoryException if a repository error occurs.
069     */
070    public static ModifiableTraversableAmetysObject getDefinitionsNode(Site site, String language) throws AmetysRepositoryException
071    {
072        try
073        {
074            // Get the root plugin node.
075            ModifiableTraversableAmetysObject pluginNode = getPluginNode(site);
076            
077            // Get or create the language node.
078            ModifiableTraversableAmetysObject langNode = getOrCreateNode(pluginNode, language, "ametys:unstructured");
079            
080            // Get or create the definitions container node in the language node and return it.
081            return getOrCreateNode(langNode, __DEFINITIONS_NODE_NAME, DefaultDefinitionFactory.DEFINITION_ROOT_NODE_TYPE);
082        }
083        catch (AmetysRepositoryException e)
084        {
085            throw new AmetysRepositoryException("Error getting the word definitions node for site " + site.getName() + " and language " + language, e);
086        }
087    }
088
089    /**
090     * Get the word definitions storage node.
091     * @param siteName the site name.
092     * @return the word definitions storage node.
093     */
094    public static String getPluginNodePath(String siteName)
095    {
096        return String.format("//element(%s, ametys:site)/ametys-internal:plugins/%s", siteName, __PLUGIN_NODE_NAME);
097    }
098    
099    /**
100     * Get the word definitions storage node.
101     * @param siteName the site name.
102     * @param language the language.
103     * @return the word definitions storage node.
104     */
105    public static String getDefinitionsNodePath(String siteName, String language)
106    {
107        return getPluginNodePath(siteName) + "/"  + language + "/" + __DEFINITIONS_NODE_NAME;
108    }
109    
110    /**
111     * Get the word definitions storage node.
112     * @param siteName the site name.
113     * @param language the language.
114     * @param expression the expression of the repository querys
115     * @return the word definitions storage node.
116     */
117    public static String getDefinitionQuery(String siteName, String language, Expression expression)
118    {
119        return getDefinitionsNodePath(siteName, language) + "/element(*, " + DefaultDefinitionFactory.DEFINITION_NODE_TYPE + ")[" + expression.build() + "] order by @ametys-internal:word";
120    }
121    
122    /**
123     * Get the word definitions storage node.
124     * @param siteName the site name.
125     * @param language the language.
126     * @param word the searched word
127     * @return the word definitions storage node.
128     */
129    public static String getWordExistsQuery(String siteName, String language, String word)
130    {
131        String lowerWord = StringUtils.replace(word, "'", "''").toLowerCase();
132        return getDefinitionsNodePath(siteName, language) + "/element(*, " + DefaultDefinitionFactory.DEFINITION_NODE_TYPE
133                + ")[fn:lower-case(@ametys-internal:word) = '" + lowerWord + "' or fn:lower-case(@ametys-internal:variants) = '" + lowerWord + "']";
134    }
135    
136    /**
137     * Get the word definitions storage node.
138     * @param siteName the site name.
139     * @param language the language.
140     * @param letter the first letter.
141     * @return the word definitions storage node.
142     */
143    public static String getFirstLetterDefQuery(String siteName, String language, String letter)
144    {
145        String lowerLetter = letter.toLowerCase();
146        return getDefinitionsNodePath(siteName, language) + "/element(*, " + DefaultDefinitionFactory.DEFINITION_NODE_TYPE
147                + ")[jcr:like(fn:lower-case(@ametys-internal:word), '" + lowerLetter + "%')] order by @ametys-internal:word";
148    }
149    
150    /**
151     * Get the word definitions storage node when first letter is not an alpha.
152     * @param siteName the site name.
153     * @param language the language.
154     * @return the word definitions storage node.
155     */
156    public static String getNonAlphaFirstLetterDefQuery(String siteName, String language)
157    {
158        return getDefinitionsNodePath(siteName, language) + "/element(*, " + DefaultDefinitionFactory.DEFINITION_NODE_TYPE
159                + ")[not(jcr:like(fn:lower-case(@ametys-internal:word), 'a%')) " 
160                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'b%'))" 
161                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'c%'))" 
162                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'd%'))" 
163                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'e%'))" 
164                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'f%'))" 
165                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'g%'))" 
166                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'h%'))" 
167                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'u%'))" 
168                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'j%'))" 
169                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'k%'))" 
170                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'l%'))" 
171                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'm%'))" 
172                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'n%'))" 
173                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'o%'))" 
174                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'p%'))" 
175                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'q%'))" 
176                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'r%'))" 
177                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 's%'))" 
178                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 't%'))" 
179                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'u%'))" 
180                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'v%'))" 
181                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'w%'))" 
182                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'x%'))" 
183                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'y%'))"
184                + "and not(jcr:like(fn:lower-case(@ametys-internal:word), 'z%'))"
185                + "] order by @ametys-internal:word";
186    }
187    
188    private static ModifiableTraversableAmetysObject getOrCreateNode(ModifiableTraversableAmetysObject parentNode, String nodeName, String nodeType) throws AmetysRepositoryException
189    {
190        ModifiableTraversableAmetysObject definitionsNode;
191        if (parentNode.hasChild(nodeName))
192        {
193            definitionsNode = parentNode.getChild(nodeName);
194        }
195        else
196        {
197            definitionsNode = parentNode.createChild(nodeName, nodeType);
198            parentNode.saveChanges();
199        }
200        return definitionsNode;
201    }
202    
203}