001    /**
002     * Copyright 2010-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.codehaus.mojo.license.header;
017    
018    import org.apache.maven.plugin.logging.Log;
019    import org.codehaus.mojo.license.header.transformer.FileHeaderTransformer;
020    import org.nuiton.processor.filters.DefaultFilter;
021    
022    /**
023     * File Header filter.
024     *
025     * @author tchemit <chemit@codelutin.com>
026     * @since 1.0
027     */
028    public abstract class FileHeaderFilter
029        extends DefaultFilter
030    {
031    
032        /**
033         * flag set to {@code true} when a header was detected (says detects both
034         * start and end process tags).
035         */
036        protected boolean touched;
037    
038        /**
039         * flag set to {@code true} when a header was detected and was modified.
040         */
041        protected boolean modified;
042    
043        /**
044         * flag set to {@code true} as soon as start process tag was detected.
045         */
046        protected boolean detectHeader;
047    
048        /**
049         * incoming default file header model
050         */
051        protected FileHeader fileHeader;
052    
053        /**
054         * header transformer
055         */
056        protected FileHeaderTransformer transformer;
057    
058        /**
059         * cached header content
060         */
061        protected String headerContent;
062    
063        /**
064         * cached full header content (with process tag + comment box)
065         */
066        protected String processTagHeaderContent;
067    
068        /**
069         * cached full header content (with process tag + comment box)
070         */
071        protected String fullHeaderContent;
072    
073        /**
074         * maven logger
075         */
076        protected Log log;
077    
078        /**
079         * Obtains the new header to use according to the old one.
080         * <p/>
081         * <b>Note:</b> If the new header should not be updated, then the result is {@code null}.
082         *
083         * @param oldHeader the old header found in file.
084         * @return {@code null} if header is still the same, otherwise the new header to apply
085         * @since 1.0
086         */
087        protected abstract FileHeader getNewHeader( FileHeader oldHeader );
088    
089        public FileHeaderFilter()
090        {
091        }
092    
093        public Log getLog()
094        {
095            return log;
096        }
097    
098        public void setLog( Log log )
099        {
100            this.log = log;
101        }
102    
103        @Override
104        protected String performInFilter( String ch )
105        {
106            if ( log.isDebugEnabled() )
107            {
108                log.debug( "performInFilter - original header =\n" + ch );
109            }
110            if ( isTouched() )
111            {
112                // Can NOT authorize two header in a same source
113                throw new IllegalStateException( "Can only have one file header start tag : " + getHeader() );
114            }
115            if ( getMatchIndexFor( ch, getHeader() ) == NOT_FOUND )
116            {
117    
118                // the header was detected, mark file to be touched
119                touched = true;
120    
121                // obtain old header model
122                FileHeaderTransformer headerTransformer = getTransformer();
123                String tmp = headerTransformer.unboxComent( ch );
124                FileHeader oldHeader = headerTransformer.toFileHeader( tmp );
125    
126                // obtain the new header (according to what to update)
127                FileHeader newFileHeader = getNewHeader( oldHeader );
128    
129                FileHeader header;
130    
131                if ( newFileHeader == null )
132                {
133    
134                    // keep the old header
135                    header = oldHeader;
136    
137                }
138                else
139                {
140    
141                    // mark that the header was updated
142                    modified = true;
143    
144                    header = newFileHeader;
145                }
146    
147                return transformer.toHeaderContent( header );
148            }
149            // Means we detects the process start tag but not the end one.
150            // coming then here from the flush filter method... So changes nothing
151            // just return the text as it comes.
152            return ch;
153        }
154    
155        @Override
156        protected String performOutFilter( String ch )
157        {
158            if ( log.isDebugEnabled() )
159            {
160                log.debug( ch );
161            }
162            return ch;
163        }
164    
165        @Override
166        protected String getHeader()
167        {
168            return getTransformer().getProcessStartTag();
169        }
170    
171        @Override
172        protected String getFooter()
173        {
174            return getTransformer().getProcessEndTag();
175        }
176    
177        @Override
178        protected void changeState( State newState )
179        {
180            super.changeState( newState );
181            if ( newState == State.SEARCH_FOOTER )
182            {
183                // on a decouvert un header
184                detectHeader = true;
185            }
186        }
187    
188        public String getHeaderContent()
189        {
190            if ( headerContent == null )
191            {
192                headerContent = getTransformer().toString( getFileHeader() );
193            }
194            return headerContent;
195        }
196    
197        public String getProcessTagHeaderContent()
198        {
199            if ( processTagHeaderContent == null )
200            {
201    
202                // box with process tag
203                processTagHeaderContent = getTransformer().boxProcessTag( getHeaderContent() );
204    
205            }
206            return processTagHeaderContent;
207        }
208    
209        public String getFullHeaderContent()
210        {
211            if ( fullHeaderContent == null )
212            {
213    
214                // box with comment
215                fullHeaderContent = getTransformer().boxComment( getProcessTagHeaderContent(), true );
216            }
217            return fullHeaderContent;
218        }
219    
220        public boolean isTouched()
221        {
222            return touched;
223        }
224    
225        public boolean isModified()
226        {
227            return modified;
228        }
229    
230        public boolean isDetectHeader()
231        {
232            return detectHeader;
233        }
234    
235        public FileHeader getFileHeader()
236        {
237            return fileHeader;
238        }
239    
240        public FileHeaderTransformer getTransformer()
241        {
242            return transformer;
243        }
244    
245        public void setFileHeader( FileHeader fileHeader )
246        {
247            this.fileHeader = fileHeader;
248        }
249    
250        public void setTransformer( FileHeaderTransformer transformer )
251        {
252            this.transformer = transformer;
253        }
254    
255        public void reset()
256        {
257            touched = false;
258            modified = false;
259            detectHeader = false;
260            state = State.SEARCH_HEADER;
261        }
262    
263        public void resetContent()
264        {
265            headerContent = null;
266            processTagHeaderContent = null;
267            fullHeaderContent = null;
268        }
269    }