View Javadoc
1   package org.apache.maven.doxia.macro.snippet;
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 java.io.BufferedReader;
23  import java.io.IOException;
24  import java.io.InputStreamReader;
25  import java.net.URL;
26  import java.util.ArrayList;
27  import java.util.List;
28  import java.util.Locale;
29  
30  import org.codehaus.plexus.util.IOUtil;
31  
32  /**
33   * Utility class for reading snippets.
34   *
35   * @version $Id: SnippetReader.java 1544338 2013-11-21 21:59:01Z michaelo $
36   */
37  public class SnippetReader
38  {
39      /** System-dependent EOL. */
40      private static final String EOL = System.getProperty( "line.separator" );
41  
42      /** The source. */
43      private URL source;
44  
45      /** The encoding of the source. */
46      private String encoding;
47  
48      /**
49       * Constructor.
50       *
51       * @param src The source
52       * @param encoding The file encoding
53       */
54      public SnippetReader( URL src, String encoding )
55      {
56          this.source = src;
57          this.encoding = encoding;
58      }
59  
60      /**
61       * Constructor.
62       *
63       * @param src The source
64       */
65      public SnippetReader( URL src )
66      {
67          this( src, null ) ;
68      }
69  
70      /**
71       * Reads the snippet with given id.
72       *
73       * @param snippetId The id of the snippet.
74       * @return The snippet.
75       * @throws java.io.IOException if something goes wrong.
76       */
77      public StringBuffer readSnippet( String snippetId )
78          throws IOException
79      {
80          List<String> lines = readLines( snippetId );
81          int minIndent = minIndent( lines );
82          StringBuffer result = new StringBuffer();
83          for ( String line : lines )
84          {
85              result.append( line.substring( minIndent ) );
86              result.append( EOL );
87          }
88          return result;
89      }
90  
91      /**
92       * Returns the minimal indent of all the lines in the given List.
93       *
94       * @param lines A List of lines.
95       * @return the minimal indent.
96       */
97      int minIndent( List<String> lines )
98      {
99          int minIndent = Integer.MAX_VALUE;
100         for ( String line : lines )
101         {
102             minIndent = Math.min( minIndent, indent( line ) );
103         }
104         return minIndent;
105     }
106 
107     /**
108      * Returns the indent of the given line.
109      *
110      * @param line A line.
111      * @return the indent.
112      */
113     int indent( String line )
114     {
115         char[] chars = line.toCharArray();
116         int indent = 0;
117         for ( ; indent < chars.length; indent++ )
118         {
119             if ( chars[indent] != ' ' )
120             {
121                 break;
122             }
123         }
124         return indent;
125     }
126 
127     /**
128      * Reads the snippet and returns the lines in a List.
129      *
130      * @param snippetId The id of the snippet.
131      * @return A List of lines.
132      * @throws IOException if something goes wrong.
133      */
134     private List<String> readLines( String snippetId )
135         throws IOException
136     {
137         BufferedReader reader;
138         if ( encoding == null || "".equals( encoding ) )
139         {
140             reader = new BufferedReader( new InputStreamReader( source.openStream() ) );
141         }
142         else
143         {
144             reader = new BufferedReader( new InputStreamReader( source.openStream(), encoding ) );
145         }
146 
147         List<String> lines = new ArrayList<String>();
148         try
149         {
150             boolean capture = false;
151             String line;
152             while ( ( line = reader.readLine() ) != null )
153             {
154                 if ( snippetId == null || "".equals( snippetId.trim() ) )
155                 {
156                     lines.add( line );
157                 }
158                 else
159                 {
160                     if ( isStart( snippetId, line ) )
161                     {
162                         capture = true;
163                     }
164                     else if ( isEnd( snippetId, line ) )
165                     {
166                         break;
167                     }
168                     else if ( capture )
169                     {
170                         lines.add( line );
171                     }
172                 }
173             }
174         }
175         finally
176         {
177             IOUtil.close( reader );
178         }
179         return lines;
180     }
181 
182     /**
183      * Determines if the given line is a start demarcator.
184      *
185      * @param snippetId the id of the snippet.
186      * @param line the line.
187      * @return True, if the line is a start demarcator.
188      */
189     protected boolean isStart( String snippetId, String line )
190     {
191         return isDemarcator( snippetId, "START", line );
192     }
193 
194     /**
195      * Determines if the given line is a demarcator.
196      *
197      * @param snippetId the id of the snippet.
198      * @param what Identifier for the demarcator.
199      * @param line the line.
200      * @return True, if the line is a start demarcator.
201      */
202     protected boolean isDemarcator( String snippetId, String what, String line )
203     {
204         String upper = line.toUpperCase( Locale.ENGLISH );
205         return upper.contains( what.toUpperCase( Locale.ENGLISH ) )
206             && upper.contains( "SNIPPET" )
207             && line.contains( snippetId );
208     }
209 
210     /**
211      * Determines if the given line is an end demarcator.
212      *
213      * @param snippetId the id of the snippet.
214      * @param line the line.
215      * @return True, if the line is an end demarcator.
216      */
217     protected boolean isEnd( String snippetId, String line )
218     {
219         return isDemarcator( snippetId, "END", line );
220     }
221 }