View Javadoc
1   /*
2    * Copyright 2012-2021 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.util;
17  
18  import static org.codelibs.core.stream.StreamUtil.split;
19  
20  import java.util.Objects;
21  import java.util.regex.Matcher;
22  import java.util.regex.Pattern;
23  
24  import org.apache.commons.lang3.StringUtils;
25  import org.codelibs.core.lang.StringUtil;
26  import org.codelibs.core.stream.StreamUtil;
27  import org.codelibs.fess.exception.FessSystemException;
28  import org.w3c.dom.Node;
29  
30  public class PrunedTag {
31      private final String tag;
32      private String id;
33      private String css;
34      private String attrName;
35      private String attrValue;
36  
37      public PrunedTag(final String tag) {
38          this.tag = tag;
39      }
40  
41      public boolean matches(final Node node) {
42          if (tag.equalsIgnoreCase(node.getNodeName())) {
43              if (attrName != null) {
44                  final Node attr = node.getAttributes().getNamedItem(attrName);
45                  if (attr == null || !attrValue.equals(attr.getNodeValue())) {
46                      return false;
47                  }
48              }
49              if (id == null) {
50                  if (css == null) {
51                      return true;
52                  }
53                  final Node classAttr = node.getAttributes().getNamedItem("class");
54                  if (classAttr != null) {
55                      final String value = classAttr.getNodeValue();
56                      if (StringUtil.isNotBlank(value)) {
57                          return StreamUtil.split(value, " ").get(stream -> stream.anyMatch(s -> css.equals(s)));
58                      }
59                  }
60              } else {
61                  final Node idAttr = node.getAttributes().getNamedItem("id");
62                  if (idAttr != null) {
63                      final String value = idAttr.getNodeValue();
64                      return id.equals(value);
65                  }
66              }
67          }
68          return false;
69      }
70  
71      @Override
72      public int hashCode() {
73          return Objects.hash(css, id, tag);
74      }
75  
76      @Override
77      public boolean equals(final Object obj) {
78          if (this == obj) {
79              return true;
80          }
81          if (obj == null) {
82              return false;
83          }
84          if (getClass() != obj.getClass()) {
85              return false;
86          }
87          final PrunedTag other = (PrunedTag) obj;
88          return StringUtils.compare(tag, other.tag) == 0 //
89                  && StringUtils.compare(css, other.css) == 0 //
90                  && StringUtils.compare(id, other.id) == 0 //
91                  && StringUtils.compare(attrName, other.attrName) == 0 //
92                  && StringUtils.compare(attrValue, other.attrValue) == 0;
93      }
94  
95      public void setId(final String id) {
96          this.id = id;
97      }
98  
99      public void setCss(final String css) {
100         this.css = css;
101     }
102 
103     public void setAttr(final String name, final String value) {
104         this.attrName = name;
105         this.attrValue = value;
106     }
107 
108     @Override
109     public String toString() {
110         return "PrunedTag [tag=" + tag + ", id=" + id + ", css=" + css + ", attrName=" + attrName + ", attrValue=" + attrValue + "]";
111     }
112 
113     public static PrunedTag[] parse(final String value) {
114         return split(value, ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(v -> {
115             final Pattern pattern = Pattern.compile("(\\w+)(\\[[^\\]]+\\])?(\\.[\\w\\-]+)?(#[\\w\\-]+)?");
116             final Matcher matcher = pattern.matcher(v.trim());
117             if (matcher.matches()) {
118                 final PrunedTag tag = new PrunedTag(matcher.group(1));
119                 if (matcher.group(2) != null) {
120                     final String attrPair = matcher.group(2).substring(1, matcher.group(2).length() - 1);
121                     final Matcher equalMatcher = Pattern.compile("([\\w\\-]+)=(\\S+)").matcher(attrPair);
122                     if (equalMatcher.matches()) {
123                         tag.setAttr(equalMatcher.group(1), equalMatcher.group(2));
124                     }
125                 }
126                 if (matcher.group(3) != null) {
127                     tag.setCss(matcher.group(3).substring(1));
128                 }
129                 if (matcher.group(4) != null) {
130                     tag.setId(matcher.group(4).substring(1));
131                 }
132                 return tag;
133             }
134             throw new FessSystemException("Invalid pruned tag: " + v);
135         }).toArray(n -> new PrunedTag[n]));
136     }
137 }