class ResourceTypeFilter extends BaseSearchFilter implements Serializable {

    public void applyRestrictions(String type, ExecutionContext context, SearchCriteria criteria) {
        SearchAttributes searchAttributes = getSearchAttributes(context);

        if (searchAttributes != null && searchAttributes.getState() != null) {
            String resourceTypeFilterOption =
                    searchAttributes.getState().getCustomFiltersMap().get("resourceTypeFilter");

            List<String> resourceTypes = null;
            if (resourceTypeFilterOption != null) {
                resourceTypes = filterOptionToResourceTypes.get(resourceTypeFilterOption);
            }

            if (CollectionUtils.isNotEmpty(resourceTypes)) {
                criteria.add(DBUtil.getBoundedInCriterion("resourceType", resourceTypes));
            }
        } else {
            final RepositorySearchCriteria repositorySearchCriteria = getTypedAttribute(context, RepositorySearchCriteria.class);
            if (repositorySearchCriteria != null) {
                final List<String> customDataSourceTypes = repositorySearchCriteria.getCustomDataSourceTypes();
                final List<String> fileResourceTypes = repositorySearchCriteria.getFileResourceTypes();
                final List<String> resourceTypes = repositorySearchCriteria.getResourceTypes();
                if (!CollectionUtils.isEmpty(resourceTypes) ||
                        !CollectionUtils.isEmpty(fileResourceTypes) ||
                        !CollectionUtils.isEmpty(customDataSourceTypes)) {
                    List<String> types = new ArrayList<String>(resourceTypes);
                    List<Criterion> includeTypes = new ArrayList<Criterion>();

                    boolean addFolders = types.remove(Folder.class.getName());
                    boolean extractTopics = types.remove("com.jaspersoft.commons.semantic.datasource.Topic");

                    //Criterion criterion = types.isEmpty()  ? null : Restrictions.in("resourceType", types);
                    Criterion criterion = null;

                    if(CollectionUtils.isNotEmpty(types)) {
                        criterion = DBUtil.getBoundedInCriterion("resourceType", types);
                    }

                    if (fileResourceTypes != null && !fileResourceTypes.isEmpty()){
                        for (String fileType : fileResourceTypes) {
                            DetachedCriteria fileTypeCriteria = DetachedCriteria.forClass(RepoFileResource.class, "U");
                            Criterion isFileType = Restrictions.eq("U.fileType", fileType);

                            fileTypeCriteria
                                    .add(isFileType)
                                    .add(Property.forName("U.id").eqProperty(criteria.getAlias() + ".id"))
                                    .setProjection(Projections.property("U.id"));

                            criterion = criterion == null ? Subqueries.exists(fileTypeCriteria) :
                                    Restrictions.or(Subqueries.exists(fileTypeCriteria), criterion);
                        }
                    }

                    if(customDataSourceTypes != null && !customDataSourceTypes.isEmpty()){
                        for (String customDataSourceType : customDataSourceTypes) {
                            DetachedCriteria customDataSourceTypeCriteria = DetachedCriteria.forClass(RepoCustomDataSource.class, "cds");

                            customDataSourceTypeCriteria
                                    .createAlias("properties", "cds_props")
                                    .add(Restrictions.eq("cds_props.name", RepoCustomDataSource.CDS_NAME_PROPERTY))
                                    .add(Restrictions.eq("cds_props.value", customDataSourceType))
                                    .add(Property.forName("cds.id").eqProperty(criteria.getAlias() + ".id"))
                                    .setProjection(Projections.property("cds.id"));

                            criterion = criterion == null ? Subqueries.exists(customDataSourceTypeCriteria) :
                                    Restrictions.or(Subqueries.exists(customDataSourceTypeCriteria), criterion);
                        }

                    }

                    if (addFolders && (ResourceLookup.class.getName().equals(type) || (types.isEmpty() && Resource.class.getName().equals(type)))) {
                        // folders only are requested
                        Criterion folderCriterion = Restrictions.isNull("resourceType");
                        criterion = criterion == null ? folderCriterion : Restrictions.or(folderCriterion, criterion);
                    }
                    if (extractTopics) {
                        extractTopics(includeTypes, criteria);
                    }
                    for (Criterion includeType : includeTypes) {
                        criterion = (criterion == null) ? includeType : Restrictions.or(criterion, includeType);
                    }

                    if (CollectionUtils.isNotEmpty(repositorySearchCriteria.getFileResourceTypes())) {
                        Criterion fileTypeCriterion = Restrictions.or(
                                DBUtil.getBoundedInCriterion("fileType", repositorySearchCriteria.getFileResourceTypes()),
                                DBUtil.getBoundedInCriterion("contentFileType", repositorySearchCriteria.getFileResourceTypes())
                        );
                        criterion = criterion == null ? fileTypeCriterion : Restrictions.or(criterion, fileTypeCriterion);
                    }

                    criteria.add(criterion);

                } else if (CollectionUtils.isNotEmpty(repositorySearchCriteria.getExcludeResourceTypes())) {
                    List<String> excludeTypes = new ArrayList<String>(repositorySearchCriteria.getExcludeResourceTypes());
                    // Additional types that require additional criterions to be search for.
                    // And only those types that are not present in excluded one
                    List<Criterion> includeTypes = new ArrayList<Criterion>();

                    Criterion criterion = Restrictions.not(DBUtil.getBoundedInCriterion("resourceType", repositorySearchCriteria.getExcludeResourceTypes()));

                    boolean addFolders = !excludeTypes.remove(Folder.class.getName());
                    boolean extractTopics = !excludeTypes.remove("com.jaspersoft.commons.semantic.datasource.Topic");
                    boolean filterSecureFileType = !excludeTypes.remove(FileResource.TYPE_SECURE_FILE);

                    if (filterSecureFileType && !excludeTypes.contains(FileResource.class.getName())) {
                        criterion = filterSecureFileTypeCriterion(criteria);
                    }
                    if (addFolders && (ResourceLookup.class.getName().equals(type))) {
                        includeTypes.add(addFoldersCriterion());
                    }
                    if (extractTopics && !excludeTypes.contains(ReportUnit.class.getName())) {
                        extractTopics(includeTypes, criteria);
                    }
                    for (Criterion includeType : includeTypes) {
                        criterion = Restrictions.or(criterion, includeType);
                    }

                    criteria.add(criterion);
                }
            } else {
                throw new RuntimeException("Resource type filter not found in the custom filters map.");
            }
        }
    }

}