View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   */
19  package org.apache.rat.configuration.builders;
20  
21  import java.util.Map;
22  
23  import org.apache.rat.analysis.IHeaderMatcher;
24  
25  /**
26   * A reference matching Matcher builder.
27   * <p>
28   * This class stores a matcher id as a reference to the matcher.  It also has a map of matcher ids to the matcher
29   * instances.  When build is called the matcher reference is looked up in the map.  If it is found then it is returned
30   * value from the {@code build()} call.  If the reference is not located then a IHeaderMatcherProxy is returned.
31   * the IHeaderMatcherProxy is resolved in a later configuration construction phase.
32   */
33  public class MatcherRefBuilder extends AbstractBuilder {
34      private String referenceId;
35      private Map<String, IHeaderMatcher> matchers;
36  
37      /**
38       * Constructs the MatcherReferenceBuilder using the provided reference id.
39       * @param refId the reverence to the matcher id.
40       * @return this builder for chaining.
41       */
42      public MatcherRefBuilder setRefId(String refId) {
43          this.referenceId = refId;
44          return this;
45      }
46  
47      /**
48       * Set the Map of matcher ids to matcher instances.
49       * @param matchers the Map of ids to instances.
50       * @return this builder for chaining.
51       */
52      public MatcherRefBuilder setMatchers(Map<String, IHeaderMatcher> matchers) {
53          this.matchers = matchers;
54          return this;
55      }
56  
57      @Override
58      public IHeaderMatcher build() {
59          IHeaderMatcher result = matchers.get(referenceId);
60          return result != null ? result : new IHeaderMatcherProxy(referenceId, matchers);
61      }
62  
63      @Override
64      public String toString() {
65          return "MathcerRefBuilder: "+referenceId;
66      }
67      
68      /**
69       * A class that is a proxy to the actual matcher.  It retrieves the actual matcher from the map of
70       * matcher ids to matcher instances one the first use of the matcher.  This allows earlier read matchers
71       * to reference later constructed matchers as long as all the matchers are constructed before the earlier one is 
72       * used.
73       */
74      private class IHeaderMatcherProxy implements IHeaderMatcher {
75          private final String proxyId;
76          private IHeaderMatcher wrapped;
77          private Map<String, IHeaderMatcher> matchers;
78  
79          private IHeaderMatcherProxy(String proxyId, Map<String, IHeaderMatcher> matchers) {
80              this.proxyId = proxyId;
81              this.matchers = matchers;
82          }
83  
84          private void checkProxy() {
85              if (wrapped == null) {
86                  wrapped = matchers.get(proxyId);
87                  if (wrapped == null) {
88                      throw new IllegalStateException(String.format("%s is not a valid matcher id", proxyId));
89                  }
90                  matchers = null;
91              }
92          }
93  
94          @Override
95          public String getId() {
96              checkProxy();
97              return wrapped.getId();
98          }
99  
100         @Override
101         public void reset() {
102             checkProxy();
103             wrapped.reset();
104         }
105 
106         @Override
107         public State matches(String line) {
108             checkProxy();
109             return wrapped.matches(line);
110         }
111 
112         @Override
113         public State currentState() {
114             checkProxy();
115             return wrapped.currentState();
116         }
117 
118         @Override
119         public State finalizeState() {
120             checkProxy();
121             return wrapped.finalizeState();
122         }
123     }
124 
125 }