/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2002-2015 Pentaho Corporation.. All rights reserved. */ package org.pentaho.platform.api.repository2.unified; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; public class RepositoryRequest { private static final Pattern FILES_TYPES_PATTERN = FILES_TYPE_FILTER.getRegExPattern(); private static final Pattern FILES_MEMBERS_INCLUDE_PATTERN = Pattern.compile( "includeMembers=(.+)" ); private static final Pattern FILES_MEMBERS_EXCLUDE_PATTERN = Pattern.compile( "excludeMembers=(.+)" ); public static final String PATH_SEPARATOR = "/"; //$NON-NLS-1$ private String path; private boolean showHidden = false; private boolean includeAcls = false; private Integer depth = -1; private FILES_TYPE_FILTER types = FILES_TYPE_FILTER.FILES_FOLDERS; private Set<String> includeMemberSet = null; private Set<String> excludeMemberSet = null; private transient String workingFilter; // temporary storage of remaining filter text as it is parsed. private String childNodeFilter; /** * This class encapsulates the parameters received by the "children" and "tree" REST calls. It provides default values * for parameters not specified and breaks down the legacy "filter" parameters into it's component parts. */ public RepositoryRequest() { } public RepositoryRequest( String path, Boolean showHidden, Integer depth, String legacyFilter ) { this.path = path; this.showHidden = showHidden == null ? false : showHidden; setDepth( depth ); setLegacyFilter( legacyFilter ); } /** * Strips out and sets the file types portion of the legacyFilter */ private void parseOutFileTypes() { // Check for File type filter types = FILES_TYPE_FILTER.FILES_FOLDERS; StringBuilder strippedFilter = new StringBuilder(); if ( !workingFilter.isEmpty() ) { String[] parts = workingFilter.split( "\\|" ); for ( String part : parts ) { Matcher m = FILES_TYPES_PATTERN.matcher( part ); if ( m.matches() ) { FILES_TYPE_FILTER newType = FILES_TYPE_FILTER.valueOf( m.group( 1 ) ); if ( newType != null ) { types = newType; // note it only makes sense to have FILES if the depth is 1 if ( types == FILES_TYPE_FILTER.FILES && depth != 1 ) { types = FILES_TYPE_FILTER.FILES_FOLDERS; } } } else { appendFilter( strippedFilter, part ); } } } workingFilter = strippedFilter.toString(); } private void appendFilter( StringBuilder strippedFilter, String part ) { if ( strippedFilter.length() != 0 ) { strippedFilter.append( "|" ); } strippedFilter.append( part ); } /** * Strips out and sets the include/exclude member sets from the filter */ private void parseOutIncludeExclude() { includeMemberSet = parseOutPattern( FILES_MEMBERS_INCLUDE_PATTERN ); excludeMemberSet = parseOutPattern( FILES_MEMBERS_EXCLUDE_PATTERN ); if ( ( includeMemberSet != null && !includeMemberSet.isEmpty() ) && ( excludeMemberSet != null && !excludeMemberSet.isEmpty() ) ) { throw new RuntimeException( "Cannot include and exclude values in the same Legacy Filter" ); } } private Set<String> parseOutPattern( Pattern pattern ) { StringBuilder strippedFilter = new StringBuilder(); String[] parts = workingFilter.split( "\\|" ); Set<String> memberSet = null; for ( String part : parts ) { Matcher m = pattern.matcher( part ); if ( m.matches() ) { String includeMembersStr = m.group( 1 ); memberSet = new HashSet<String>( Arrays.asList( includeMembersStr.split( "," ) ) ); } else { appendFilter( strippedFilter, part ); } } workingFilter = strippedFilter.toString(); return memberSet; } public enum FILES_TYPE_FILTER { FILES, FOLDERS, FILES_FOLDERS; public static Pattern getRegExPattern() { StringBuilder sb = new StringBuilder( "(PLACEHOLDER" ); for ( FILES_TYPE_FILTER val : FILES_TYPE_FILTER.values() ) { sb.append( "|" ).append( val.toString() ); } sb.append( ")" ); return Pattern.compile( sb.toString() ); } } private void setLegacyFilter( String legacyFilter ) { this.workingFilter = ( legacyFilter == null || StringUtils.isEmpty( legacyFilter ) ) ? "*" : legacyFilter; parseOutFileTypes(); parseOutIncludeExclude(); childNodeFilter = workingFilter.isEmpty() ? null : workingFilter; workingFilter = null; //garbage collect } public FILES_TYPE_FILTER getTypes() { return types; } /** * Sets whether files, folders, or both are returned: ( FILES | FOLDERS | [default] FILES_FOLDERS ) */ public void setTypes( FILES_TYPE_FILTER types ) { this.types = types; } public Set<String> getIncludeMemberSet() { return includeMemberSet; } /** * @param includeMemberSet A set of field names to be included in the output. */ public void setIncludeMemberSet( Set<String> includeMemberSet ) { this.includeMemberSet = includeMemberSet; } public Set<String> getExcludeMemberSet() { return excludeMemberSet; } /** * @param includeMemberSet A set of field names to be excluded in the output. */ public void setExcludeMemberSet( Set<String> excludeMemberSet ) { this.excludeMemberSet = excludeMemberSet; } public boolean isShowHidden() { return showHidden; } /** * @param showHidden * Whether to return information about hidden files. Default is false. */ public void setShowHidden( boolean showHidden ) { this.showHidden = showHidden; } public Integer getDepth() { return depth; } /** * @param depth * 0 fetches just file at path; positive integer n fetches node at path plus n levels of children; negative * integer fetches all children. If n > 0 and {@link RepositoryRequest#setTypes(FILES_TYPE_FILTER)} is set to * FILES then only the top level children will be processed. */ public void setDepth( Integer depth ) { if ( depth == null ) { depth = -1; // search all } this.depth = depth; } public String getChildNodeFilter() { return childNodeFilter; } /** * @param childNodefilter * filter may be a full name or a partial name with one or more wildcard characters ("*"), or a disjunction * (using the "|" character to represent logical OR) of these; filter does not apply to root node. */ public void setChildNodeFilter( String childNodeFilter ) { this.childNodeFilter = childNodeFilter; } public String getPath() { return path; } /** * @param path * Path to file */ public void setPath( String path ) { this.path = path; } public boolean isIncludeAcls() { return includeAcls; } /** * * @param includeAcls * Set to true to return ACL permission information with the output. Default is false. */ public void setIncludeAcls( boolean includeAcls ) { this.includeAcls = includeAcls; } }