View Javadoc

1   package org.apache.onami.configuration.variables;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static java.lang.String.format;
23  import static java.util.logging.Level.FINEST;
24  import static java.util.logging.Logger.getLogger;
25  
26  import java.util.Map;
27  import java.util.logging.Logger;
28  
29  /**
30   * Abstract Appender implementation handling resolving context management.
31   *
32   * @since 6.2
33   */
34  abstract class AbstractAppender
35      implements Appender
36  {
37  
38      /** Logger */
39      private static final Logger logger = getLogger( AbstractAppender.class.getName() );
40  
41      /** Original chunk to process by this appender */
42      protected final String chunk;
43  
44      /**
45       * Default constructor
46       *
47       * @param chunk The chunk this appender has to process.
48       */
49      protected AbstractAppender( String chunk )
50      {
51          this.chunk = chunk;
52      }
53  
54      /**
55       * Move provided context to current appender and call {@link #doAppend(StringBuilder, Map, Tree, Parser)} if no recursion has been detected.
56       *
57       * @param buffer
58       * @param configuration
59       * @param context
60       */
61      public final void append( StringBuilder buffer, Map<String, String> configuration, Tree<Appender> context )
62      {
63          // Create context if needed
64          Tree<Appender> currentContext = context == null ? new Tree<Appender>( this ) : context.addLeaf( this );
65  
66          // Check recursion
67          if ( currentContext.inAncestors( this ) )
68          {
69              // For the moment just log a warning, and stop the resolving by appending original chunk
70              buffer.append( chunk );
71  
72              logger.warning( format( "Recursion detected within variable resolving:%n%s", currentContext.getRoot() ) );
73          }
74          // Process real appending
75          else
76          {
77              doAppend( buffer, configuration, currentContext );
78              // Dump some info on resolution if this is a root appender
79              if ( currentContext.isRoot() && logger.isLoggable( FINEST ) )
80              {
81                  logger.finest( format( "Resolving variables:%n%s", currentContext ) );
82              }
83          }
84      }
85  
86      /**
87       * Begin resolving process with this appender against the provided configuration.
88       */
89      public String resolve( Map<String, String> configuration )
90      {
91          StringBuilder buffer = new StringBuilder();
92          append( buffer, configuration, null );
93          return buffer.toString();
94      }
95  
96      /**
97       * Append something to the provided buffer for the given configuration.<br>
98       *
99       * @param buffer
100      * @param configuration
101      * @param passed Resolving context, current element is the appender itself.
102      */
103     protected abstract void doAppend( StringBuilder buffer, Map<String, String> configuration, Tree<Appender> context );
104 
105     /**
106      * Abstract to force subclasses to re-implement.
107      */
108     @Override
109     public abstract boolean equals( Object obj );
110 
111     /**
112      * Abstract to force subclasses to re-implement.
113      */
114     @Override
115     public abstract int hashCode();
116 
117     /**
118      * @return original chunk
119      */
120     @Override
121     public final String toString()
122     {
123         return chunk;
124     }
125 
126 }