001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.security;
029
030import org.opencms.main.CmsIllegalArgumentException;
031import org.opencms.util.CmsMacroResolver;
032import org.opencms.util.CmsStringUtil;
033import org.opencms.util.CmsUUID;
034
035import java.util.Locale;
036
037/**
038 * An organizational unit in OpenCms.<p>
039 *
040 * Be sure the flags does not conflict with the flags defined in {@link org.opencms.file.CmsResource}.<p>
041 *
042 * @since 6.5.6
043 */
044public class CmsOrganizationalUnit {
045
046    /** The flag constant to hide the organizational units from the login form. */
047    public static final int FLAG_HIDE_LOGIN = 1;
048
049    /** The flag constant to mark the organizational units as containing only webusers. */
050    public static final int FLAG_WEBUSERS = 8;
051
052    /** The character used to separate each level in a fully qualified name. */
053    public static final String SEPARATOR = "/";
054
055    /** The description of this organizational unit. */
056    private String m_description;
057
058    /** The flags of this organizational unit. */
059    private int m_flags;
060
061    /** The unique id of this organizational unit. */
062    private final CmsUUID m_id;
063
064    /** The fully qualified name of this organizational unit. */
065    private final String m_name;
066
067    /** The id of the related default project. */
068    private final CmsUUID m_projectId;
069
070    /**
071     * Creates a new OpenCms organizational unit principal.
072     *
073     * @param id the unique id of the organizational unit
074     * @param fqn the fully qualified name of the this organizational unit (should end with slash)
075     * @param description the description of the organizational unit
076     * @param flags the flags of the organizational unit
077     * @param projectId the id of the related default project
078     */
079    public CmsOrganizationalUnit(CmsUUID id, String fqn, String description, int flags, CmsUUID projectId) {
080
081        m_id = id;
082        m_name = fqn;
083        m_description = description;
084        m_flags = flags;
085        m_projectId = projectId;
086    }
087
088    /**
089     * Returns the parent fully qualified name.<p>
090     *
091     * This is <code>null</code> for the root ou, and
092     * the empty string for first level ous.<p>
093     *
094     * @param fqn the fully qualified name to get the parent from
095     *
096     * @return the parent fully qualified name
097     */
098    public static final String getParentFqn(String fqn) {
099
100        if (CmsStringUtil.isEmptyOrWhitespaceOnly(fqn)) {
101            // in case of the root ou
102            return null;
103        }
104        int pos;
105        if (fqn.endsWith(CmsOrganizationalUnit.SEPARATOR)) {
106            pos = fqn.substring(0, fqn.length() - 1).lastIndexOf(CmsOrganizationalUnit.SEPARATOR);
107        } else {
108            pos = fqn.lastIndexOf(CmsOrganizationalUnit.SEPARATOR);
109        }
110        if (pos <= 0) {
111            // in case of simple names assume root ou
112            return "";
113        }
114        return fqn.substring(0, pos + 1);
115    }
116
117    /**
118     * Returns the last name of the given fully qualified name.<p>
119     *
120     * @param fqn the fully qualified name to get the last name from
121     *
122     * @return the last name of the given fully qualified name
123     */
124    public static final String getSimpleName(String fqn) {
125
126        String parentFqn = getParentFqn(fqn);
127        if (parentFqn != null) {
128            fqn = fqn.substring(parentFqn.length());
129        }
130        if ((fqn != null) && fqn.startsWith(CmsOrganizationalUnit.SEPARATOR)) {
131            fqn = fqn.substring(CmsOrganizationalUnit.SEPARATOR.length());
132        }
133        return fqn;
134    }
135
136    /**
137     * Prefixes a simple name with an OU.<p>
138     *
139     * @param ou the OU to use as a prefix
140     * @param principal the simple name to which the OU should be prepended
141     *
142     * @return the FQN
143     */
144    public static String prefixWithOu(String ou, String principal) {
145
146        String result = CmsStringUtil.joinPaths(ou, principal);
147        if (result.startsWith("/")) {
148            result = result.substring(1);
149        }
150        return result;
151    }
152
153    /**
154     * Returns the given fully qualified name without leading separator.<p>
155     *
156     * @param fqn the fully qualified name to fix
157     *
158     * @return the given fully qualified name without leading separator
159     */
160    public static String removeLeadingSeparator(String fqn) {
161
162        if ((fqn != null) && fqn.startsWith(CmsOrganizationalUnit.SEPARATOR)) {
163            return fqn.substring(1);
164        }
165        return fqn;
166    }
167
168    /**
169     * Adds the given flag to the flags for this organizational unit.<p>
170     *
171     * @param flag the flag to add
172     */
173    public void addFlag(int flag) {
174
175        m_flags = (m_flags ^ flag);
176    }
177
178    /**
179     * @see java.lang.Object#clone()
180     */
181    @Override
182    public Object clone() {
183
184        return new CmsOrganizationalUnit(m_id, m_name, m_description, m_flags, m_projectId);
185    }
186
187    /**
188     * @see java.lang.Object#equals(java.lang.Object)
189     */
190    @Override
191    public boolean equals(Object obj) {
192
193        if (obj == this) {
194            return true;
195        }
196        if (obj instanceof CmsOrganizationalUnit) {
197            if (m_id != null) {
198                return m_id.equals(((CmsOrganizationalUnit)obj).getId());
199            }
200        }
201        return false;
202    }
203
204    /**
205     * Returns the description of this organizational unit.<p>
206     *
207     * This could return also just a macro, so please use the
208     * {@link #getDescription(Locale)} method.<p>
209     *
210     * @return the description of this organizational unit
211     */
212    public String getDescription() {
213
214        return m_description;
215    }
216
217    /**
218     * Returns the description of this organizational unit.<p>
219     *
220     * @param locale the locale
221     *
222     * @return the description of this organizational unit
223     */
224    public String getDescription(Locale locale) {
225
226        CmsMacroResolver macroResolver = new CmsMacroResolver();
227        macroResolver.setMessages(org.opencms.db.generic.Messages.get().getBundle(locale));
228        return macroResolver.resolveMacros(m_description);
229    }
230
231    /**
232     * Returns the display name for this organizational unit.<p>
233     *
234     * @param locale the locale
235     *
236     * @return the display name for this organizational unit
237     */
238    public String getDisplayName(Locale locale) {
239
240        if (getParentFqn() == null) {
241            // for the root ou
242            return getDescription(locale);
243        }
244        return Messages.get().getBundle(locale).key(
245            Messages.GUI_ORGUNIT_DISPLAY_NAME_2,
246            getDescription(locale),
247            CmsOrganizationalUnit.SEPARATOR + getName());
248    }
249
250    /**
251     * Returns the flags of this organizational unit.<p>
252     *
253     * The organizational unit flags are used to store special information about the
254     * organizational unit state encoded bitwise. Usually the flags int value should not
255     * be directly accessed. <p>
256     *
257     * @return the flags of this organizational unit
258     */
259    public int getFlags() {
260
261        return m_flags;
262    }
263
264    /**
265     * Returns the id of this organizational unit.
266     *
267     * @return the id of this organizational unit.
268     */
269    public CmsUUID getId() {
270
271        return m_id;
272    }
273
274    /**
275     * Returns the fully qualified name of this organizational unit.<p>
276     *
277     * @return the fully qualified name of this organizational unit
278     */
279    public String getName() {
280
281        return m_name;
282    }
283
284    /**
285     * Returns the full qualified name of the parent organizational unit of this organizational unit.<p>
286     *
287     * This is <code>null</code> for the root ou, and the empty string for first level ous.<p>
288     *
289     * @return the full qualified name of the parent organizational unit of this organizational unit
290     */
291    public String getParentFqn() {
292
293        return getParentFqn(m_name);
294    }
295
296    /**
297     * Returns the id of the related default project.<p>
298     *
299     * @return the id of the related default project
300     */
301    public CmsUUID getProjectId() {
302
303        return m_projectId;
304    }
305
306    /**
307     * Returns the simple name of this organizational unit.
308     *
309     * @return the simple name of this organizational unit.
310     */
311    public String getSimpleName() {
312
313        return getSimpleName(m_name);
314    }
315
316    /**
317     * Checks if this organizational unit has the given flag set.<p>
318     *
319     * @param flag the flag to check
320     *
321     * @return <code>true</code> if this organizational unit has the given flag set
322     */
323    public boolean hasFlag(int flag) {
324
325        return (m_flags & flag) == flag;
326    }
327
328    /**
329     * Checks if this organizational unit has the "hide from login form" flag set.<p>
330     *
331     * @return <code>true</code> if this organizational unit has the "hide from login form" flag set
332     */
333    public boolean hasFlagHideLogin() {
334
335        return hasFlag(FLAG_HIDE_LOGIN);
336    }
337
338    /**
339     * Checks if this organizational unit has the "webusers" flag set.<p>
340     *
341     * @return <code>true</code> if this organizational unit has the "webusers" flag set
342     */
343    public boolean hasFlagWebuser() {
344
345        return hasFlag(FLAG_WEBUSERS);
346    }
347
348    /**
349     * @see java.lang.Object#hashCode()
350     */
351    @Override
352    public int hashCode() {
353
354        if (m_id != null) {
355            return m_id.hashCode();
356        }
357        return CmsUUID.getNullUUID().hashCode();
358    }
359
360    /**
361     * Sets the description of this organizational unit.<p>
362     *
363     * @param description the principal organizational unit to set
364     */
365    public void setDescription(String description) {
366
367        if (CmsStringUtil.isEmptyOrWhitespaceOnly(description)) {
368            throw new CmsIllegalArgumentException(
369                org.opencms.db.Messages.get().container(org.opencms.db.Messages.ERR_BAD_OU_DESCRIPTION_EMPTY_0));
370        }
371
372        m_description = description;
373    }
374
375    /**
376     * Sets the "hide from login form" flag.<p>
377     */
378    public void setFlagHideLogin() {
379
380        addFlag(FLAG_HIDE_LOGIN);
381    }
382
383    /**
384     * Sets this organizational unit flags to the specified value.<p>
385     *
386     * The organizational unit flags are used to store special information about the
387     * organizational units state encoded bitwise. Usually the flags int value should not
388     * be directly accessed. <p>
389     *
390     * @param value the value to set this organizational units flags to
391     */
392    public void setFlags(int value) {
393
394        m_flags = value;
395    }
396
397    /**
398     * Sets the "webusers" flag.<p>
399     */
400    public void setFlagWebusers() {
401
402        addFlag(FLAG_WEBUSERS);
403    }
404
405    /**
406     * @see java.lang.Object#toString()
407     */
408    @Override
409    public String toString() {
410
411        StringBuffer result = new StringBuffer();
412        result.append("[Organizational Unit]");
413        result.append(" fqn:");
414        result.append(getName());
415        result.append(" id:");
416        result.append(m_id);
417        result.append(" description:");
418        result.append(m_description);
419        return result.toString();
420    }
421}