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.core.user.UserIdentity;
019import org.ametys.plugins.repository.RepositoryConstants;
020
021/**
022 * Constructs an {@link Expression} corresponding to a user comparison store as a composite with login and id of population.
023 */
024public class UserExpression implements Expression
025{
026    private UserIdentity _user;
027    private Operator _operator;
028    private String _metadata;
029    private boolean _multiple;
030    private ExpressionContext _context;
031    
032    /**
033     * Creates the comparison Expression.
034     * @param metadata the metadata path
035     * @param operator the operator to make the comparison
036     * @param value the user identity as login#population.
037     */
038    public UserExpression(String metadata, Operator operator, String value)
039    {
040        this(metadata, operator, value, ExpressionContext.newInstance());
041    }
042    
043    /**
044     * Creates the comparison Expression.
045     * @param metadata the metadata path
046     * @param operator the operator to make the comparison
047     * @param value the user identity as login#population.
048     * @param context the expression context
049     */
050    public UserExpression(String metadata, Operator operator, String value, ExpressionContext context)
051    {
052        this(metadata, operator, value, false, context);
053    }
054    
055    /**
056     * Creates the comparison Expression.
057     * @param metadata the metadata path
058     * @param operator the operator to make the comparison
059     * @param value the user identity as login#population.
060     * @param multiple true if the attribute is multiple
061     */
062    public UserExpression(String metadata, Operator operator, String value, boolean multiple)
063    {
064        this(metadata, operator, value, multiple, ExpressionContext.newInstance());
065    }
066    
067    /**
068     * Creates the comparison Expression.
069     * @param metadata the metadata path
070     * @param operator the operator to make the comparison
071     * @param value the user identity as login#population.
072     * @param multiple true if the attribute is multiple
073     * @param context the expression context
074     */
075    public UserExpression(String metadata, Operator operator, String value, boolean multiple, ExpressionContext context)
076    {
077        this(metadata, operator, UserIdentity.stringToUserIdentity(value), multiple, context);
078    }
079    
080    /**
081     * Creates the comparison Expression.
082     * @param metadata the metadata path
083     * @param operator the operator to make the comparison
084     * @param userIdentity the user identity (login and population)
085     */
086    public UserExpression(String metadata, Operator operator, UserIdentity userIdentity)
087    {
088        this(metadata, operator, userIdentity, ExpressionContext.newInstance());
089    }
090    
091    /**
092     * Creates the comparison Expression.
093     * @param metadata the metadata path
094     * @param operator the operator to make the comparison
095     * @param userIdentity the user identity (login and population)
096     * @param context the expression context
097     */
098    public UserExpression(String metadata, Operator operator, UserIdentity userIdentity, ExpressionContext context)
099    {
100        this(metadata, operator, userIdentity, false, context);
101    }
102    
103    /**
104     * Creates the comparison Expression.
105     * @param metadata the metadata path
106     * @param operator the operator to make the comparison
107     * @param userIdentity the user identity (login and population)
108     * @param multiple true if the attribute is multiple
109     */
110    public UserExpression(String metadata, Operator operator, UserIdentity userIdentity, boolean multiple)
111    {
112        this(metadata, operator, userIdentity, multiple, ExpressionContext.newInstance());
113    }
114    
115    /**
116     * Creates the comparison Expression.
117     * @param metadata the metadata path
118     * @param operator the operator to make the comparison
119     * @param userIdentity the user identity (login and population)
120     * @param multiple true if the attribute is multiple
121     * @param context the expression context
122     */
123    public UserExpression(String metadata, Operator operator, UserIdentity userIdentity, boolean multiple, ExpressionContext context)
124    {
125        _user = userIdentity;
126        _metadata = metadata;
127        _operator = operator;
128        _multiple = multiple;
129        _context = context;
130    }
131    
132    @Override
133    public String build()
134    {
135        Expression expr = new AndExpression(new UserLoginExpression(_metadata, _operator, _user.getLogin(), _multiple, _context), new UserPopulationExpression(_metadata, _operator, _user.getPopulationId(), _multiple, _context));
136        return expr.build();
137    }
138    
139    /**
140     * Internal class to create a expression based on a user's login comparison
141     */
142    class UserLoginExpression implements Expression
143    {
144        private String _uleValue;
145        private Operator _uleOperator;
146        
147        private String _uleMetadata;
148        private String _ulePath;
149        private boolean _uleMultiple;
150        private ExpressionContext _uleContext;
151        
152        /**
153         * Construction an expression to test a user login
154         * @param metadata The path to metadata
155         * @param operator The operator
156         * @param value The login value
157         * @param multiple true if the attribute is multiple
158         * @param context the expression context
159         */
160        public UserLoginExpression(String metadata, Operator operator, String value, boolean multiple, ExpressionContext context)
161        {
162            _uleValue = value;
163            _uleOperator = operator;
164            
165            int index = metadata.lastIndexOf('/');
166            boolean isComposite = index != -1;
167            _ulePath = isComposite ? metadata.substring(0, index) : null;
168            _uleMetadata = isComposite ? metadata.substring(index + 1) : metadata;
169            _uleMultiple = multiple;
170            _uleContext = context;
171        }
172        
173        @Override
174        public String build()
175        {
176            StringBuilder buff = new StringBuilder();
177            String repositoryPrefix = _uleContext.internal() ? RepositoryConstants.NAMESPACE_PREFIX_INTERNAL : RepositoryConstants.NAMESPACE_PREFIX;
178            
179            if (_uleContext.unversioned())
180            {
181                buff.append(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL).append(":unversioned/");
182            }
183            
184            if (_ulePath != null)
185            {
186                String[] parts = _ulePath.split("/");
187                for (String part : parts)
188                {
189                    if ("*".equals(part))
190                    {
191                        buff.append(part).append('/');
192                    }
193                    else
194                    {
195                        buff.append(repositoryPrefix).append(':').append(part).append('/');
196                    }
197                    
198                }
199            }
200            
201            buff.append(repositoryPrefix).append(':').append(_uleMetadata).append('/');
202            
203            if (_uleMultiple)
204            {
205                buff.append("*/");
206            }
207            
208            buff.append('@').append(repositoryPrefix).append(':').append("login");
209            buff.append(" " + _uleOperator);
210            buff.append(" '" + _uleValue.replaceAll("'", "''") + "'");
211            
212            return buff.toString();
213        }
214    }
215    
216    /**
217     * Internal class to create a expression based on a user's population comparison
218     */
219    class UserPopulationExpression implements Expression
220    {
221        private String _upeValue;
222        private Operator _upeOperator;
223        
224        private String _upeMetadata;
225        private String _upePath;
226        private boolean _upeMultiple;
227        private ExpressionContext _upeContext;
228        
229        /**
230         * Construction an expression to test a user population
231         * @param metadata The path to metadata
232         * @param operator The operator
233         * @param value The population's id
234         * @param multiple true if the attribute is multiple
235         * @param context the expression context
236         */
237        public UserPopulationExpression(String metadata, Operator operator, String value, boolean multiple, ExpressionContext context)
238        {
239            _upeValue = value;
240            _upeOperator = operator;
241            
242            int index = metadata.lastIndexOf('/');
243            boolean isComposite = index != -1;
244            _upePath = isComposite ? metadata.substring(0, index) : null;
245            _upeMetadata = isComposite ? metadata.substring(index + 1) : metadata;
246            _upeMultiple = multiple;
247            _upeContext = context;
248        }
249        
250        @Override
251        public String build()
252        {
253            StringBuilder buff = new StringBuilder();
254            String repositoryPrefix = _upeContext.internal() ? RepositoryConstants.NAMESPACE_PREFIX_INTERNAL : RepositoryConstants.NAMESPACE_PREFIX;
255            
256            if (_upeContext.unversioned())
257            {
258                buff.append(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL).append(":unversioned/");
259            }
260            
261            if (_upePath != null)
262            {
263                String[] parts = _upePath.split("/");
264                for (String part : parts)
265                {
266                    if ("*".equals(part))
267                    {
268                        buff.append(part).append('/');
269                    }
270                    else
271                    {
272                        buff.append(repositoryPrefix).append(':').append(part).append('/');
273                    }
274                    
275                }
276            }
277            
278            buff.append(repositoryPrefix).append(':').append(_upeMetadata).append('/');
279            
280            if (_upeMultiple)
281            {
282                buff.append("*/");
283            }
284            
285            buff.append('@').append(repositoryPrefix).append(':').append("population");
286            buff.append(" " + _upeOperator);
287            buff.append(" '" + _upeValue + "'");
288            
289            return buff.toString();
290        }
291    }
292}