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 *    https://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.subtree.SubtreeSpecification;
028
029
030/**
031 * Defines a set of zero or more users the permissions apply to.
032 * 
033 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
034 */
035public abstract class UserClass
036{
037    /**
038     * Every directory user (with possible requirements for
039     * authenticationLevel).
040     */
041    public static final AllUsers ALL_USERS = new AllUsers();
042
043    /**
044     * The user with the same distinguished name as the entry being accessed, or
045     * if the entry is a member of a family, then additionally the user with the
046     * distinguished name of the ancestor.
047     */
048    public static final ThisEntry THIS_ENTRY = new ThisEntry();
049
050    /**
051     * The user as parent (ancestor) of accessed entry.
052     */
053    public static final ParentOfEntry PARENT_OF_ENTRY = new ParentOfEntry();
054
055
056    /**
057     * Creates a new instance.
058     */
059    protected UserClass()
060    {
061    }
062    
063
064    /**
065     * Every directory user (with possible requirements for
066     * authenticationLevel).
067     */
068    public static final class AllUsers extends UserClass
069    {
070        /**
071         * Creates a new instance of AllUsers.
072         */
073        private AllUsers()
074        {
075        }
076
077
078        /**
079         * {@inheritDoc}
080         */
081        @Override
082        public String toString()
083        {
084            return "allUsers";
085        }
086    }
087    
088
089    /**
090     * The user with the same distinguished name as the entry being accessed, or
091     * if the entry is a member of a family, then additionally the user with the
092     * distinguished name of the ancestor.
093     */
094    public static final class ThisEntry extends UserClass
095    {
096        /**
097         * Creates a new instance of ThisEntry.
098         */
099        private ThisEntry()
100        {
101        }
102
103
104        /**
105         * {@inheritDoc}
106         */
107        @Override
108        public String toString()
109        {
110            return "thisEntry";
111        }
112    }
113    
114
115    /**
116     * The user as parent (ancestor) of accessed entry.
117     */
118    public static final class ParentOfEntry extends UserClass
119    {
120        /**
121         * Creates a new instance of ParentOfEntry.
122         */
123        private ParentOfEntry()
124        {
125        }
126
127
128        /**
129         * {@inheritDoc}
130         */
131        @Override
132        public String toString()
133        {
134            return "parentOfEntry";
135        }
136    }
137    
138
139    /**
140     * A base class for all user classes which has a set of DNs.
141     */
142    private abstract static class NamedUserClass extends UserClass
143    {
144        /** The names. */
145        protected final Set<String> names;
146
147
148        /**
149         * Creates a new instance.
150         * 
151         * @param names a set of names
152         */
153        protected NamedUserClass( Set<String> names )
154        {
155            if ( names == null )
156            {
157                this.names = Collections.unmodifiableSet( new HashSet<String>() );
158            }
159            else
160            {
161                this.names = Collections.unmodifiableSet( new HashSet<String>( names ) );
162            }
163        }
164
165
166        /**
167         * Returns the set of all names.
168         * 
169         * @return The set of all names
170         */
171        public Set<String> getNames()
172        {
173            return names;
174        }
175
176
177        /**
178         * {@inheritDoc}
179         */
180        @Override
181        public boolean equals( Object o )
182        {
183            if ( this == o )
184            {
185                return true;
186            }
187            
188            if ( !( o instanceof NamedUserClass ) )
189            {
190                return false;
191            }
192
193            if ( getClass().isAssignableFrom( o.getClass() ) )
194            {
195                Name that = ( Name ) o;
196                
197                return names.equals( that.names );
198            }
199
200            return false;
201        }
202
203
204        /**
205         * {@inheritDoc}
206         */
207        @Override
208        public int hashCode()
209        {
210            int result = 37;
211
212            // Use a slightly different hashcode here : we multiple
213            // each DN in the set with the result to have a result that
214            // is not dependent on the DN order in the Set.
215            // In order to avoid result of 0 if one of the DN hashcode,
216            // we discard them.
217            for ( String dn : names )
218            {
219                int h = dn.hashCode();
220                
221                if ( h != 0 )
222                {
223                    result = result * h;
224                }
225            }
226
227            return result;
228        }
229
230
231        /**
232         * {@inheritDoc}
233         */
234        @Override
235        public String toString()
236        {
237            StringBuilder buffer = new StringBuilder();
238
239            boolean isFirst = true;
240            buffer.append( "{ " );
241
242            for ( String 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 );
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<String> 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<String> 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}