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.relations;
029
030import org.opencms.file.CmsResource;
031import org.opencms.util.CmsUUID;
032
033import java.util.Collections;
034import java.util.HashSet;
035import java.util.Iterator;
036import java.util.Set;
037
038/**
039 * A filter to retrieve the relations for a given resource.<p>
040 *
041 * @since 6.0.0
042 */
043public final class CmsRelationFilter implements Cloneable {
044
045    /** To filter all sources and targets. */
046    public static final CmsRelationFilter ALL = new CmsRelationFilter(true, true);
047
048    /** To filter all sources. */
049    public static final CmsRelationFilter SOURCES = new CmsRelationFilter(true, false);
050
051    /** To filter all targets. */
052    public static final CmsRelationFilter TARGETS = new CmsRelationFilter(false, true);
053
054    /** If set the filter extends the result to the given path and all its subresources. */
055    private boolean m_includeSubresources;
056
057    /** To filter relations for a given source path. */
058    private String m_path;
059
060    /** If set the filter looks for matching targets. */
061    private boolean m_source;
062
063    /** The structure id of the resource to filter. */
064    private CmsUUID m_structureId;
065
066    /** If set the filter looks for matching sources. */
067    private boolean m_target;
068
069    /** The types to filter. */
070    private Set<CmsRelationType> m_types = new HashSet<CmsRelationType>();
071
072    /**
073     * Private constructor.<p>
074     *
075     * @param source if set the filter looks for matching targets
076     * @param target if set the filter looks for matching sources
077     */
078    private CmsRelationFilter(boolean source, boolean target) {
079
080        m_source = source;
081        m_target = target;
082    }
083
084    /**
085     * Utility method which prepares a filter for relations which point *from* a given structure id.<p>
086     *
087     * @param structureId the structure id
088     *
089     * @return the new relation filter
090     */
091    public static CmsRelationFilter relationsFromStructureId(CmsUUID structureId) {
092
093        return SOURCES.filterStructureId(structureId);
094    }
095
096    /**
097     * Utility method which prepares a filter for relations which point *to* a given structure id.<p>
098     *
099     * @param structureId the structure id
100     *
101     * @return the new relation filter
102     */
103    public static CmsRelationFilter relationsToStructureId(CmsUUID structureId) {
104
105        return TARGETS.filterStructureId(structureId);
106    }
107
108    /**
109     * @see java.lang.Object#clone()
110     */
111    @Override
112    public Object clone() {
113
114        CmsRelationFilter filter = new CmsRelationFilter(m_source, m_target);
115        filter.m_structureId = m_structureId;
116        filter.m_types = new HashSet<CmsRelationType>(m_types);
117        filter.m_path = m_path;
118        filter.m_includeSubresources = m_includeSubresources;
119        return filter;
120    }
121
122    /**
123     * Returns an extended filter with defined in content type restriction.<p>
124     *
125     * @return an extended filter with defined in content type restriction
126     */
127    public CmsRelationFilter filterDefinedInContent() {
128
129        CmsRelationFilter filter = (CmsRelationFilter)clone();
130        if (filter.m_types.isEmpty()) {
131            filter.m_types.addAll(CmsRelationType.getAllDefinedInContent());
132        } else {
133            filter.m_types = new HashSet<CmsRelationType>(CmsRelationType.filterDefinedInContent(filter.m_types));
134        }
135        return filter;
136    }
137
138    /**
139     * Returns an extended filter that will extend the result to the given path and all its subresources.<p>
140     *
141     * @return an extended filter with including subresources
142     */
143    public CmsRelationFilter filterIncludeChildren() {
144
145        CmsRelationFilter filter = (CmsRelationFilter)clone();
146        filter.m_includeSubresources = true;
147        return filter;
148    }
149
150    /**
151     * Returns an extended filter with internal type restriction.<p>
152     *
153     * @return an extended filter with internal type restriction
154     */
155    public CmsRelationFilter filterInternal() {
156
157        CmsRelationFilter filter = (CmsRelationFilter)clone();
158        if (filter.m_types.isEmpty()) {
159            filter.m_types.addAll(CmsRelationType.getAllInternal());
160        } else {
161            filter.m_types = new HashSet<CmsRelationType>(CmsRelationType.filterInternal(filter.m_types));
162        }
163        return filter;
164    }
165
166    /**
167     * Returns an extended filter with not defined in content type restriction.<p>
168     *
169     * @return an extended filter with not defined in content type restriction
170     */
171    public CmsRelationFilter filterNotDefinedInContent() {
172
173        CmsRelationFilter filter = (CmsRelationFilter)clone();
174        if (filter.m_types.isEmpty()) {
175            filter.m_types.addAll(CmsRelationType.getAllNotDefinedInContent());
176        } else {
177            filter.m_types = new HashSet<CmsRelationType>(CmsRelationType.filterNotDefinedInContent(filter.m_types));
178        }
179        return filter;
180    }
181
182    /**
183     * Returns an extended filter with the given source relation path restriction.<p>
184     *
185     * @param path the source relation path to filter
186     *
187     * @return an extended filter with the given source relation path restriction
188     */
189    public CmsRelationFilter filterPath(String path) {
190
191        CmsRelationFilter filter = (CmsRelationFilter)clone();
192        filter.m_path = path;
193        return filter;
194    }
195
196    /**
197     * Returns an extended filter with the given resource (path and id) restriction.<p>
198     *
199     * @param resource the resource to filter
200     *
201     * @return an extended filter with the given resource (path and id) restriction
202     */
203    public CmsRelationFilter filterResource(CmsResource resource) {
204
205        CmsRelationFilter filter = filterStructureId(resource.getStructureId());
206        filter = filterPath(resource.getRootPath());
207        return filter;
208    }
209
210    /**
211     * Returns an extended filter with strong type restriction.<p>
212     *
213     * @return an extended filter with strong type restriction
214     */
215    public CmsRelationFilter filterStrong() {
216
217        CmsRelationFilter filter = (CmsRelationFilter)clone();
218        if (filter.m_types.isEmpty()) {
219            filter.m_types.addAll(CmsRelationType.getAllStrong());
220        } else {
221            filter.m_types = new HashSet<CmsRelationType>(CmsRelationType.filterStrong(filter.m_types));
222        }
223        return filter;
224    }
225
226    /**
227     * Returns an extended filter with the given structure id restriction.<p>
228     *
229     * @param structureId the structure id to filter
230     *
231     * @return an extended filter with the given structure id restriction
232     */
233    public CmsRelationFilter filterStructureId(CmsUUID structureId) {
234
235        CmsRelationFilter filter = (CmsRelationFilter)clone();
236        filter.m_structureId = structureId;
237        return filter;
238    }
239
240    /**
241     * Returns an extended filter with the given type restriction.<p>
242     *
243     * @param type the relation type to filter
244     *
245     * @return an extended filter with the given type restriction
246     */
247    public CmsRelationFilter filterType(CmsRelationType type) {
248
249        CmsRelationFilter filter = (CmsRelationFilter)clone();
250        filter.m_types.add(type);
251        return filter;
252    }
253
254    /**
255     * Returns an extended filter with user defined type restriction.<p>
256     *
257     * @return an extended filter with user defined type restriction
258     */
259    public CmsRelationFilter filterUserDefined() {
260
261        CmsRelationFilter filter = (CmsRelationFilter)clone();
262        if (filter.m_types.isEmpty()) {
263            filter.m_types.addAll(CmsRelationType.getAllUserDefined());
264        } else {
265            filter.m_types = new HashSet<CmsRelationType>(CmsRelationType.filterUserDefined(filter.m_types));
266        }
267        return filter;
268    }
269
270    /**
271     * Returns an extended filter with weak type restriction.<p>
272     *
273     * @return an extended filter with weak type restriction
274     */
275    public CmsRelationFilter filterWeak() {
276
277        CmsRelationFilter filter = (CmsRelationFilter)clone();
278        if (filter.m_types.isEmpty()) {
279            filter.m_types.addAll(CmsRelationType.getAllWeak());
280        } else {
281            filter.m_types = new HashSet<CmsRelationType>(CmsRelationType.filterWeak(filter.m_types));
282        }
283        return filter;
284    }
285
286    /**
287     * Returns the source relation path restriction.<p>
288     *
289     * @return the source relation path restriction
290     */
291    public String getPath() {
292
293        return m_path;
294    }
295
296    /**
297     * Returns the structure Id of the resource to filter.<p>
298     *
299     * @return the structure Id of the resource to filter
300     */
301    public CmsUUID getStructureId() {
302
303        return m_structureId;
304    }
305
306    /**
307     * Returns the types to filter.<p>
308     *
309     * @return the types to filter
310     */
311    public Set<CmsRelationType> getTypes() {
312
313        return Collections.unmodifiableSet(m_types);
314    }
315
316    /**
317     * Checks if this filter includes relations defined in the content.<p>
318     *
319     * @return <code>true</code> if this filter includes relations defined in the content
320     */
321    public boolean includesDefinedInContent() {
322
323        if ((m_types == null) || m_types.isEmpty()) {
324            return true;
325        }
326        Iterator<CmsRelationType> itTypes = m_types.iterator();
327        while (itTypes.hasNext()) {
328            CmsRelationType type = itTypes.next();
329            if (type.isDefinedInContent()) {
330                return true;
331            }
332        }
333        return false;
334    }
335
336    /**
337     * Returns the include subresources flag.<p>
338     *
339     * @return if set the filter extends the result to the given path and all its subresources
340     */
341    public boolean isIncludeSubresources() {
342
343        return m_includeSubresources;
344    }
345
346    /**
347     * Returns the source flag.<p>
348     *
349     * @return if set the filter looks for matching targets
350     */
351    public boolean isSource() {
352
353        return m_source;
354    }
355
356    /**
357     * Returns the target flag.<p>
358     *
359     * @return if set the filter looks for matching sources
360     */
361    public boolean isTarget() {
362
363        return m_target;
364    }
365
366    /**
367     * Returns <code>true</code> if the given relation type matches this filter.<p>
368     *
369     * @param type the relation type to test
370     *
371     * @return if the given relation type matches this filter
372     */
373    public boolean matchType(CmsRelationType type) {
374
375        if (m_types.isEmpty()) {
376            return true;
377        }
378        return m_types.contains(type);
379    }
380
381    /**
382     * @see java.lang.Object#toString()
383     */
384    @Override
385    public String toString() {
386
387        StringBuffer str = new StringBuffer(128);
388        str.append("[");
389        String mode = null;
390        if (m_source) {
391            if (m_target) {
392                mode = "both";
393            } else {
394                mode = "source";
395            }
396        } else {
397            if (m_target) {
398                mode = "target";
399            } else {
400                mode = "none";
401            }
402        }
403        str.append(mode).append("=").append(m_structureId).append(", ");
404        str.append("path").append("=").append(m_path).append(", ");
405        str.append("types").append("=").append(m_types).append(", ");
406        str.append("subresources").append("=").append(m_includeSubresources);
407        str.append("]");
408        return str.toString();
409    }
410}