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.lock;
029
030import org.opencms.file.CmsUser;
031import org.opencms.util.CmsUUID;
032
033import java.util.Collections;
034import java.util.HashSet;
035import java.util.Set;
036
037/**
038 * A filter to retrieve the locks.<p>
039 *
040 * @since 6.5.4
041 */
042public final class CmsLockFilter implements Cloneable {
043
044    /** To filter all locks. */
045    public static final CmsLockFilter FILTER_ALL = new CmsLockFilter(true).filterIncludeChildren();
046
047    /** To filter all inherited locks. */
048    public static final CmsLockFilter FILTER_INHERITED = new CmsLockFilter(true);
049
050    /** To filter all non inherited locks. */
051    public static final CmsLockFilter FILTER_NON_INHERITED = new CmsLockFilter(false);
052
053    /** If set the filter restricts the result excluding locks owned by the given user. */
054    private CmsUUID m_notOwnedByUserId;
055
056    /** If set the filter extends the result to non inherited locks. */
057    private boolean m_includeChildren;
058
059    /** If set the filter restricts the result including only locks owned by the given user. */
060    private CmsUUID m_ownedByUserId;
061
062    /** If set the filter extends the result to inherited locks. */
063    private boolean m_includeParents;
064
065    /** If set the filter restricts the result to the given project. */
066    private CmsUUID m_projectId;
067
068    /** If set the filter also matches shared exclusive locks. */
069    private boolean m_sharedExclusive;
070
071    /** The types to filter. */
072    private Set<CmsLockType> m_types = new HashSet<CmsLockType>();
073
074    /** If set the filter restricts the result excluding locks not lockable by the given user. */
075    private CmsUser m_notLockableByUser;
076
077    /** If set the filter restricts the result including only locks lockable by the given user. */
078    private CmsUser m_lockableByUser;
079
080    /**
081     * Private constructor.<p>
082     *
083     * @param inherited if the this lock filter should checks inherited locks or not
084     */
085    private CmsLockFilter(boolean inherited) {
086
087        m_includeChildren = !inherited;
088        m_includeParents = inherited;
089    }
090
091    /**
092     * @see java.lang.Object#clone()
093     */
094    @Override
095    public Object clone() {
096
097        CmsLockFilter filter = new CmsLockFilter(false);
098        filter.m_includeChildren = m_includeChildren;
099        filter.m_includeParents = m_includeParents;
100        filter.m_types = new HashSet<CmsLockType>(m_types);
101        filter.m_ownedByUserId = m_ownedByUserId;
102        filter.m_notOwnedByUserId = m_notOwnedByUserId;
103        filter.m_projectId = m_projectId;
104        filter.m_notLockableByUser = m_notLockableByUser;
105        filter.m_lockableByUser = m_lockableByUser;
106        return filter;
107    }
108
109    /**
110     * Returns an extended filter with the given user restriction.<p>
111     *
112     * @param userId the user id to filter
113     *
114     * @return an extended filter with the given user restriction
115     */
116    public CmsLockFilter filterNotOwnedByUserId(CmsUUID userId) {
117
118        CmsLockFilter filter = (CmsLockFilter)clone();
119        filter.m_notOwnedByUserId = userId;
120        return filter;
121    }
122
123    /**
124     * Returns an extended filter with the given user restriction.<p>
125     *
126     * @param user the user to filter
127     *
128     * @return an extended filter with the given user restriction
129     */
130    public CmsLockFilter filterNotLockableByUser(CmsUser user) {
131
132        CmsLockFilter filter = (CmsLockFilter)clone();
133        filter.m_notLockableByUser = user;
134        return filter;
135    }
136
137    /**
138     * Returns an extended filter with the given user restriction.<p>
139     *
140     * @param user the user to filter
141     *
142     * @return an extended filter with the given user restriction
143     */
144    public CmsLockFilter filterLockableByUser(CmsUser user) {
145
146        CmsLockFilter filter = (CmsLockFilter)clone();
147        filter.m_lockableByUser = user;
148        return filter;
149    }
150
151    /**
152     * Returns an extended filter that will extend the result to the given path and all its children.<p>
153     *
154     * @return an extended filter to search the subresources of the given path
155     */
156    public CmsLockFilter filterIncludeChildren() {
157
158        CmsLockFilter filter = (CmsLockFilter)clone();
159        filter.m_includeChildren = true;
160        return filter;
161    }
162
163    /**
164     * Returns an extended filter with the given user restriction.<p>
165     *
166     * @param userId the user id to filter
167     *
168     * @return an extended filter with the given user restriction
169     */
170    public CmsLockFilter filterOwnedByUserId(CmsUUID userId) {
171
172        CmsLockFilter filter = (CmsLockFilter)clone();
173        filter.m_ownedByUserId = userId;
174        return filter;
175    }
176
177    /**
178     * Returns an extended filter that will extend the result to the given path and all its parents.<p>
179     *
180     * @return an extended filter to search the subresources of the given path
181     */
182    public CmsLockFilter filterIncludeParents() {
183
184        CmsLockFilter filter = (CmsLockFilter)clone();
185        filter.m_includeParents = true;
186        return filter;
187    }
188
189    /**
190     * Returns an extended filter with the given project restriction.<p>
191     *
192     * @param projectId the project to filter the locks with
193     *
194     * @return an extended filter with the given project restriction
195     */
196    public CmsLockFilter filterProject(CmsUUID projectId) {
197
198        CmsLockFilter filter = (CmsLockFilter)clone();
199        filter.m_projectId = projectId;
200        return filter;
201    }
202
203    /**
204     * Returns an extended filter that also matches shared exclusive locks (siblings).<p>
205     *
206     * @return an extended filter that also matches shared exclusive locks
207     */
208    public CmsLockFilter filterSharedExclusive() {
209
210        CmsLockFilter filter = (CmsLockFilter)clone();
211        filter.m_sharedExclusive = true;
212        return filter;
213    }
214
215    /**
216     * Returns an extended filter with the given type restriction.<p>
217     *
218     * @param type the lock type to filter
219     *
220     * @return an extended filter with the given type restriction
221     */
222    public CmsLockFilter filterType(CmsLockType type) {
223
224        CmsLockFilter filter = (CmsLockFilter)clone();
225        filter.m_types.add(type);
226        return filter;
227    }
228
229    /**
230     * Returns the user that has to own the locks.<p>
231     *
232     * @return the user that has to own the locks
233     */
234    public CmsUUID getOwnedByUserId() {
235
236        return m_ownedByUserId;
237    }
238
239    /**
240     * Returns the user that has not to own the locks.<p>
241     *
242     * @return the user that has not to own the locks
243     */
244    public CmsUUID getNotOwnedByUserId() {
245
246        return m_notOwnedByUserId;
247    }
248
249    /**
250     * Returns the user that can overwrite the locks.<p>
251     *
252     * @return the user that can overwrite the locks
253     */
254    public CmsUser getLockableByUserId() {
255
256        return m_lockableByUser;
257    }
258
259    /**
260     * Returns the user that can not overwrite the locks.<p>
261     *
262     * @return the user that can not overwrite the locks
263     */
264    public CmsUser getNotLockableByUserId() {
265
266        return m_notLockableByUser;
267    }
268
269    /**
270     * Returns the project restriction.<p>
271     *
272     * @return the project restriction
273     */
274    public CmsUUID getProjectId() {
275
276        return m_projectId;
277    }
278
279    /**
280     * Returns the types to filter.<p>
281     *
282     * @return the types to filter
283     */
284    public Set<CmsLockType> getTypes() {
285
286        return Collections.unmodifiableSet(m_types);
287    }
288
289    /**
290     * Returns the include children flag.<p>
291     *
292     * @return if set the filter extends the result to the given path and all its children
293     */
294    public boolean isIncludeChildren() {
295
296        return m_includeChildren;
297    }
298
299    /**
300     * Returns the include parents flag.<p>
301     *
302     * @return if set the filter extends the result to the given path and all its parents
303     */
304    public boolean isIncludeParent() {
305
306        return m_includeParents;
307    }
308
309    /**
310     * Returns the <code>true</code> if this filter also matches shared exclusive locks.<p>
311     *
312     * @return the <code>true</code> if this filter also matches shared exclusive locks
313     */
314    public boolean isSharedExclusive() {
315
316        return m_sharedExclusive;
317    }
318
319    /**
320     * Matches the given lock against this filter and the given path.<p>
321     *
322     * @param rootPath the path to match the lock against
323     * @param lock the lock to match
324     *
325     * @return <code>true</code> if the given lock matches
326     */
327    public boolean match(String rootPath, CmsLock lock) {
328
329        boolean match = false;
330        if (m_includeChildren) {
331            // safe since rootPath always ends with slash if a folder
332            match = lock.getResourceName().startsWith(rootPath);
333        }
334        if (!match && m_includeParents) {
335            // since parents can only be folders, check it only for folders
336            if (lock.getResourceName().endsWith("/")) {
337                match = rootPath.startsWith(lock.getResourceName());
338            }
339        }
340        if (match && (m_projectId != null) && !m_projectId.isNullUUID() && (lock.getProjectId() != null)) {
341            match = lock.getProjectId().equals(m_projectId);
342        }
343        if (match && (m_ownedByUserId != null) && !m_ownedByUserId.isNullUUID()) {
344            match = lock.getUserId().equals(m_ownedByUserId);
345        }
346        if (match && (m_notOwnedByUserId != null) && !m_notOwnedByUserId.isNullUUID()) {
347            match = !lock.getUserId().equals(m_notOwnedByUserId);
348        }
349        if (match && (m_lockableByUser != null)) {
350            match = lock.isLockableBy(m_lockableByUser);
351        }
352        if (match && (m_notLockableByUser != null)) {
353            match = !lock.isLockableBy(m_notLockableByUser);
354        }
355        if (match && !m_types.isEmpty()) {
356            match = m_types.contains(lock.getType());
357            match = match || (m_includeParents && lock.isInherited());
358        }
359        // check the related lock if available
360        if (!match && !lock.getRelatedLock().isNullLock()) {
361            match = match(rootPath, lock.getRelatedLock());
362        }
363        return match;
364    }
365
366    /**
367     * @see java.lang.Object#toString()
368     */
369    @Override
370    public String toString() {
371
372        StringBuffer str = new StringBuffer(128);
373        str.append("[");
374        str.append("children").append("=").append(m_includeChildren).append(", ");
375        str.append("parents").append("=").append(m_includeParents).append(", ");
376        str.append("types").append("=").append(m_types).append(", ");
377        str.append("includedUser").append("=").append(m_ownedByUserId).append(", ");
378        str.append("excludedUser").append("=").append(m_notOwnedByUserId).append(", ");
379        str.append("project").append("=").append(m_projectId).append(", ");
380        str.append("lockableBy").append("=").append(m_lockableByUser).append(", ");
381        str.append("notLockableBy").append("=").append(m_notLockableByUser).append(", ");
382        str.append("includeShared").append("=").append(m_sharedExclusive);
383        str.append("]");
384        return str.toString();
385    }
386}