View Javadoc
1   /**
2    * This file Copyright (c) 2013-2016 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.rssaggregator.importhandler;
35  
36  import info.magnolia.module.rssaggregator.util.Assert;
37  
38  import java.util.Set;
39  
40  import org.apache.commons.beanutils.MethodUtils;
41  import org.apache.commons.lang3.StringUtils;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  import com.rometools.rome.feed.synd.SyndEntry;
46  
47  /**
48   * Filters entries based on the criteria specified in the RSS Aggregator dialog.
49   */
50  public class PlanetFilter {
51  
52      private static final Logger log = LoggerFactory.getLogger(PlanetFilter.class);
53      private static final String METHOD_PREFIX = "get";
54      private final Set<FilterPredicate> filters;
55  
56      public PlanetFilter(Set<FilterPredicate> filters) {
57          Assert.notNull(filters, "'filters' must not be null");
58          this.filters = filters;
59      }
60  
61      public boolean include(SyndEntry entry) {
62          boolean includeAnd = includeByCondition(entry, FilterPredicate.Condition.AND);
63          boolean includeOr = includeByCondition(entry, FilterPredicate.Condition.OR);
64          boolean includeNot = includeByCondition(entry, FilterPredicate.Condition.NOT);
65  
66          return includeAnd && includeOr && includeNot;
67      }
68  
69      boolean includeByCondition(SyndEntry entry, FilterPredicate.Condition matchingCondition) {
70          boolean include = false;
71          boolean conditionFound = false;
72  
73          for (FilterPredicate filter : filters) {
74              Object propertyValue = getPropertyValue(entry, filter.getProperty());
75              FilterPredicate.Condition condition = filter.getCondition();
76  
77              if (propertyValue != null && condition.equals(matchingCondition)) {
78                  boolean hit;
79  
80                  hit = matchSingleString(propertyValue.toString(), filter.getRegularExpression());
81  
82                  switch (condition) {
83                  case AND:
84                      if (hit && !conditionFound) {
85                          include = true;
86                      } else {
87                          include &= hit;
88                      }
89                      conditionFound = true;
90                      break;
91                  case OR:
92                      if (hit) {
93                          include = true;
94                      }
95                      conditionFound = true;
96                      break;
97                  case NOT:
98                      if (hit) {
99                          include = false;
100                     } else {
101                         if (!conditionFound) {
102                             include = true;
103                         }
104                     }
105                     conditionFound = true;
106                     break;
107                 }
108             }
109         }
110         if (!conditionFound) {
111             include = true;
112         }
113         return include;
114     }
115 
116     protected boolean matchSingleString(String propertyValue, String regularExpression) {
117         // remove newline characters, otherwise regex will not work
118         propertyValue = StringUtils.remove(propertyValue, "\n");
119 
120         return propertyValue.matches(regularExpression);
121     }
122 
123     Object getPropertyValue(SyndEntry entry, String property) {
124         Object propertyValue = StringUtils.EMPTY;
125 
126         String getterName = getCamelCaseProperty(property);
127 
128         try {
129             propertyValue = MethodUtils.invokeExactMethod(entry, getterName, null);
130         } catch (Exception e) {
131             if (log.isWarnEnabled()) {
132                 log.warn("Property {} can't be retrieved from the feed and will be treated as if it was empty during filtering", property);
133             }
134         }
135 
136         return propertyValue;
137     }
138 
139     protected String getCamelCaseProperty(String prop) {
140         if (StringUtils.isBlank(prop)) {
141             return "";
142         }
143         return METHOD_PREFIX + StringUtils.upperCase(StringUtils.substring(prop, 0, 1)) +
144                 StringUtils.lowerCase((StringUtils.substring(prop, 1, prop.length())));
145     }
146 }