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        public String toString()
236        {
237            StringBuilder buffer = new StringBuilder();
238
239            boolean isFirst = true;
240            buffer.append( "{ " );
241
242            for ( Dn name : names )
243            {
244                if ( isFirst )
245                {
246                    isFirst = false;
247                }
248                else
249                {
250                    buffer.append( ", " );
251                }
252
253                buffer.append( '"' );
254                buffer.append( name.toString() );
255                buffer.append( '"' );
256            }
257
258            buffer.append( " }" );
259
260            return buffer.toString();
261        }
262    }
263    
264
265    /**
266     * The user with the specified distinguished name.
267     */
268    public static class Name extends NamedUserClass
269    {
270        /**
271         * Creates a new instance.
272         * 
273         * @param usernames the set of user DNs.
274         */
275        public Name( Set<Dn> usernames )
276        {
277            super( usernames );
278        }
279
280
281        /**
282         * {@inheritDoc}
283         */
284        @Override
285        public String toString()
286        {
287            return "name " + super.toString();
288        }
289    }
290    
291
292    /**
293     * The set of users who are members of the groupOfUniqueNames entry,
294     * identified by the specified distinguished name. Members of a group of
295     * unique names are treated as individual object names, and not as the names
296     * of other groups of unique names.
297     */
298    public static class UserGroup extends NamedUserClass
299    {
300        /**
301         * Creates a new instance.
302         * 
303         * @param groupNames the set of group DNs.
304         */
305        public UserGroup( Set<Dn> groupNames )
306        {
307            super( groupNames );
308        }
309
310
311        /**
312         * {@inheritDoc}
313         */
314        @Override
315        public String toString()
316        {
317            return "userGroup " + super.toString();
318        }
319    }
320    
321
322    /**
323     * The set of users whose distinguished names fall within the definition of
324     * the (unrefined) subtree.
325     */
326    public static class Subtree extends UserClass
327    {
328        /** The subtree specifications. */
329        protected final Set<SubtreeSpecification> subtreeSpecifications;
330
331
332        /**
333         * Creates a new instance.
334         * 
335         * @param subtreeSpecs the collection of unrefined {@link SubtreeSpecification}s.
336         */
337        public Subtree( Set<SubtreeSpecification> subtreeSpecs )
338        {
339            subtreeSpecifications = Collections.unmodifiableSet( subtreeSpecs );
340        }
341
342
343        /**
344         * Returns the collection of unrefined {@link SubtreeSpecification}s.
345         *
346         * @return the subtree specifications
347         */
348        public Set<SubtreeSpecification> getSubtreeSpecifications()
349        {
350            return subtreeSpecifications;
351        }
352
353
354        /**
355         * {@inheritDoc}
356         */
357        @Override
358        public int hashCode()
359        {
360            int hash = 37;
361            hash = hash * 17 + subtreeSpecifications.hashCode();
362
363            return hash;
364        }
365
366
367        /**
368         * {@inheritDoc}
369         */
370        @Override
371        public boolean equals( Object o )
372        {
373            if ( this == o )
374            {
375                return true;
376            }
377
378            if ( o instanceof Subtree )
379            {
380                Subtree that = ( Subtree ) o;
381                
382                return subtreeSpecifications.equals( that.subtreeSpecifications );
383            }
384
385            return false;
386        }
387
388
389        /**
390         * {@inheritDoc}
391         */
392        @Override
393        public String toString()
394        {
395            StringBuilder buffer = new StringBuilder();
396
397            boolean isFirst = true;
398            buffer.append( "subtree { " );
399
400            for ( SubtreeSpecification ss : subtreeSpecifications )
401            {
402                if ( isFirst )
403                {
404                    isFirst = false;
405                }
406                else
407                {
408                    buffer.append( ", " );
409                }
410
411                ss.toString( buffer );
412            }
413
414            buffer.append( " }" );
415
416            return buffer.toString();
417        }
418    }
419}