001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.api.ldap.aci;
021
022
023import java.util.Collections;
024import java.util.HashSet;
025import java.util.Set;
026
027import org.apache.directory.api.ldap.model.name.Dn;
028import org.apache.directory.api.ldap.model.subtree.SubtreeSpecification;
029
030
031/**
032 * Defines a set of zero or more users the permissions apply to.
033 * 
034 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
035 */
036public abstract class UserClass
037{
038    /**
039     * Every directory user (with possible requirements for
040     * authenticationLevel).
041     */
042    public static final AllUsers ALL_USERS = new AllUsers();
043
044    /**
045     * The user with the same distinguished name as the entry being accessed, or
046     * if the entry is a member of a family, then additionally the user with the
047     * distinguished name of the ancestor.
048     */
049    public static final ThisEntry THIS_ENTRY = new ThisEntry();
050
051    /**
052     * The user as parent (ancestor) of accessed entry.
053     */
054    public static final ParentOfEntry PARENT_OF_ENTRY = new ParentOfEntry();
055
056
057    /**
058     * Creates a new instance.
059     */
060    protected UserClass()
061    {
062    }
063    
064
065    /**
066     * Every directory user (with possible requirements for
067     * authenticationLevel).
068     */
069    public static final class AllUsers extends UserClass
070    {
071        /**
072         * Creates a new instance of AllUsers.
073         */
074        private AllUsers()
075        {
076        }
077
078
079        /**
080         * {@inheritDoc}
081         */
082        @Override
083        public String toString()
084        {
085            return "allUsers";
086        }
087    }
088    
089
090    /**
091     * The user with the same distinguished name as the entry being accessed, or
092     * if the entry is a member of a family, then additionally the user with the
093     * distinguished name of the ancestor.
094     */
095    public static final class ThisEntry extends UserClass
096    {
097        /**
098         * Creates a new instance of ThisEntry.
099         */
100        private ThisEntry()
101        {
102        }
103
104
105        /**
106         * {@inheritDoc}
107         */
108        @Override
109        public String toString()
110        {
111            return "thisEntry";
112        }
113    }
114    
115
116    /**
117     * The user as parent (ancestor) of accessed entry.
118     */
119    public static final class ParentOfEntry extends UserClass
120    {
121        /**
122         * Creates a new instance of ParentOfEntry.
123         */
124        private ParentOfEntry()
125        {
126        }
127
128
129        /**
130         * {@inheritDoc}
131         */
132        @Override
133        public String toString()
134        {
135            return "parentOfEntry";
136        }
137    }
138    
139
140    /**
141     * A base class for all user classes which has a set of DNs.
142     */
143    private abstract static class NamedUserClass extends UserClass
144    {
145        /** The names. */
146        protected final Set<Dn> names;
147
148
149        /**
150         * Creates a new instance.
151         * 
152         * @param names a set of names
153         */
154        protected NamedUserClass( Set<Dn> names )
155        {
156            if ( names == null )
157            {
158                this.names = Collections.unmodifiableSet( new HashSet<Dn>() );
159            }
160            else
161            {
162                this.names = Collections.unmodifiableSet( new HashSet<Dn>( names ) );
163            }
164        }
165
166
167        /**
168         * Returns the set of all names.
169         * 
170         * @return The set of all names
171         */
172        public Set<Dn> getNames()
173        {
174            return names;
175        }
176
177
178        /**
179         * {@inheritDoc}
180         */
181        @Override
182        public boolean equals( Object o )
183        {
184            if ( this == o )
185            {
186                return true;
187            }
188
189            if ( o == null )
190            {
191                return false;
192            }
193
194            if ( getClass().isAssignableFrom( o.getClass() ) )
195            {
196                Name that = ( Name ) o;
197                
198                return names.equals( that.names );
199            }
200
201            return false;
202        }
203
204
205        /**
206         * {@inheritDoc}
207         */
208        @Override
209        public int hashCode()
210        {
211            int result = 37;
212
213            // Use a slightly different hashcode here : we multiple
214            // each DN in the set with the result to have a result that
215            // is not dependent on the DN order in the Set.
216            // In order to avoid result of 0 if one of the DN hashcode,
217            // we discard them.
218            for ( Dn dn : this.names )
219            {
220                int h = dn.hashCode();
221                
222                if ( h != 0 )
223                {
224                    result = result * h;
225                }
226            }
227
228            return result;
229        }
230
231
232        /**
233         * {@inheritDoc}
234         */
235        @Override
236        public String toString()
237        {
238            StringBuilder buffer = new StringBuilder();
239
240            boolean isFirst = true;
241            buffer.append( "{ " );
242
243            for ( Dn name : names )
244            {
245                if ( isFirst )
246                {
247                    isFirst = false;
248                }
249                else
250                {
251                    buffer.append( ", " );
252                }
253
254                buffer.append( '"' );
255                buffer.append( name.toString() );
256                buffer.append( '"' );
257            }
258
259            buffer.append( " }" );
260
261            return buffer.toString();
262        }
263    }
264    
265
266    /**
267     * The user with the specified distinguished name.
268     */
269    public static class Name extends NamedUserClass
270    {
271        /**
272         * Creates a new instance.
273         * 
274         * @param usernames the set of user DNs.
275         */
276        public Name( Set<Dn> usernames )
277        {
278            super( usernames );
279        }
280
281
282        /**
283         * {@inheritDoc}
284         */
285        @Override
286        public String toString()
287        {
288            return "name " + super.toString();
289        }
290    }
291    
292
293    /**
294     * The set of users who are members of the groupOfUniqueNames entry,
295     * identified by the specified distinguished name. Members of a group of
296     * unique names are treated as individual object names, and not as the names
297     * of other groups of unique names.
298     */
299    public static class UserGroup extends NamedUserClass
300    {
301        /**
302         * Creates a new instance.
303         * 
304         * @param groupNames the set of group DNs.
305         */
306        public UserGroup( Set<Dn> groupNames )
307        {
308            super( groupNames );
309        }
310
311
312        /**
313         * {@inheritDoc}
314         */
315        @Override
316        public String toString()
317        {
318            return "userGroup " + super.toString();
319        }
320    }
321    
322
323    /**
324     * The set of users whose distinguished names fall within the definition of
325     * the (unrefined) subtree.
326     */
327    public static class Subtree extends UserClass
328    {
329        /** The subtree specifications. */
330        protected final Set<SubtreeSpecification> subtreeSpecifications;
331
332
333        /**
334         * Creates a new instance.
335         * 
336         * @param subtreeSpecs the collection of unrefined {@link SubtreeSpecification}s.
337         */
338        public Subtree( Set<SubtreeSpecification> subtreeSpecs )
339        {
340            subtreeSpecifications = Collections.unmodifiableSet( subtreeSpecs );
341        }
342
343
344        /**
345         * Returns the collection of unrefined {@link SubtreeSpecification}s.
346         *
347         * @return the subtree specifications
348         */
349        public Set<SubtreeSpecification> getSubtreeSpecifications()
350        {
351            return subtreeSpecifications;
352        }
353
354
355        /**
356         * {@inheritDoc}
357         */
358        @Override
359        public int hashCode()
360        {
361            int hash = 37;
362            hash = hash * 17 + subtreeSpecifications.hashCode();
363
364            return hash;
365        }
366
367
368        /**
369         * {@inheritDoc}
370         */
371        @Override
372        public boolean equals( Object o )
373        {
374            if ( this == o )
375            {
376                return true;
377            }
378
379            if ( o instanceof Subtree )
380            {
381                Subtree that = ( Subtree ) o;
382                
383                return subtreeSpecifications.equals( that.subtreeSpecifications );
384            }
385
386            return false;
387        }
388
389
390        /**
391         * {@inheritDoc}
392         */
393        @Override
394        public String toString()
395        {
396            StringBuilder buffer = new StringBuilder();
397
398            boolean isFirst = true;
399            buffer.append( "subtree { " );
400
401            for ( SubtreeSpecification ss : subtreeSpecifications )
402            {
403                if ( isFirst )
404                {
405                    isFirst = false;
406                }
407                else
408                {
409                    buffer.append( ", " );
410                }
411
412                ss.toString( buffer );
413            }
414
415            buffer.append( " }" );
416
417            return buffer.toString();
418        }
419    }
420}