001package org.apache.maven.doxia.module.fo;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024import java.util.List;
025
026import javax.swing.text.MutableAttributeSet;
027import javax.swing.text.SimpleAttributeSet;
028
029import org.apache.commons.configuration.ConfigurationException;
030import org.apache.commons.configuration.XMLConfiguration;
031
032import org.apache.maven.doxia.sink.SinkUtils;
033import org.codehaus.plexus.util.ReaderFactory;
034
035/**
036 * A utility class to construct FO configuration parameters.
037 *
038 * @author ltheussl
039 * @version $Id$
040 * @since 1.1
041 */
042public class FoConfiguration
043{
044    /** Holds the single attributes. */
045    private MutableAttributeSet attributeSet;
046
047    /** The configuration instance. */
048    private final XMLConfiguration config;
049
050    /** The list of attribute sets. */
051    private List<?> sets;
052
053    /**
054     * Constructor.
055     */
056    public FoConfiguration()
057    {
058        this.config = new XMLConfiguration();
059
060        // necessary because some attributes contain commas:
061        config.setDelimiterParsingDisabled( true );
062
063        loadDefaultConfig();
064    }
065
066    /**
067     * Load configuration parameters from a File.
068     *
069     * @param configFile the configuration file.
070     *
071     * @throws java.io.IOException if the File cannot be read
072     *  or some error occurs when initializing the configuration parameters.
073     *
074     * @since 1.1.1
075     */
076    public void load( File configFile )
077            throws IOException
078    {
079        config.clear();
080
081        try
082        {
083            config.load( configFile );
084        }
085        catch ( ConfigurationException cex )
086        {
087            IOException ioe = new IOException();
088            ioe.initCause( cex );
089            throw ioe;
090        }
091
092        loadDefaultConfig(); // this adds default values that are missing from above
093    }
094
095    /**
096     * Builds a list of attributes.
097     *
098     * @param attributeId A unique id to identify the set of attributes.
099     * This should correspond to the name of an attribute-set
100     * defined in the configuration file.
101     * @return A string that contains a list of attributes with
102     * the values configured for the current builder. Returns the
103     * empty string if attributeId is null or if attributeId
104     * is not a valid identifier.
105     */
106    public String getAttributeString( String attributeId )
107    {
108        if ( attributeId == null )
109        {
110            return "";
111        }
112
113        reset();
114        addAttributes( attributeId );
115
116        return SinkUtils.getAttributeString( attributeSet );
117    }
118
119    /**
120     * Builds a set of attributes.
121     *
122     * @param attributeId A unique id to identify the set of attributes.
123     * This should correspond to the name of an attribute-set
124     * defined in the configuration file.
125     * @return A MutableAttributeSet that contains the attributes with
126     * the values configured for the current builder. Returns null
127     * if attributeId is null or empty, or if attributeId is not a valid identifier.
128     */
129    public MutableAttributeSet getAttributeSet( String attributeId )
130    {
131        if ( attributeId == null || attributeId.length() == 0 )
132        {
133            return null;
134        }
135
136        reset();
137        addAttributes( attributeId );
138
139        if ( attributeSet.getAttributeCount() == 0 )
140        {
141            return null;
142        }
143
144        return attributeSet;
145    }
146
147    /**
148     * Adds an attribute to the current StringBuilder.
149     *
150     * @param attributeId A unique id to identify the set of attributes.
151     * This should correspond to the name of an attribute-set
152     * defined in the configuration file.
153     */
154    private void addAttributes( String attributeId )
155    {
156        int index = sets.indexOf( attributeId );
157        String keybase = "xsl:attribute-set(" + String.valueOf( index ) + ")";
158
159        Object prop = config.getProperty( keybase + ".xsl:attribute" );
160
161        if ( prop instanceof List<?> )
162        {
163            List<?> values = (List<?>) prop;
164            List<?> keys = config.getList( keybase + ".xsl:attribute[@name]" );
165
166            for ( int i = 0; i < values.size(); i++ )
167            {
168                attributeSet.addAttribute( keys.get( i ), values.get( i ) );
169            }
170        }
171        else if ( prop instanceof String )
172        {
173            String value = config.getString( keybase + ".xsl:attribute" );
174            String key = config.getString( keybase + ".xsl:attribute[@name]" );
175            attributeSet.addAttribute( key, value );
176        }
177
178        String extend = config.getString( keybase + "[@use-attribute-sets]" );
179
180        if ( extend != null )
181        {
182            addAttributes( extend );
183        }
184    }
185
186    /** Load the default fo configuration file. */
187    private void loadDefaultConfig()
188    {
189        try
190        {
191            config.load( ReaderFactory.newXmlReader( getClass().getResourceAsStream( "/fo-styles.xslt" ) ) );
192        }
193        catch ( ConfigurationException cex )
194        {
195            // this should not happen
196            throw new RuntimeException( cex );
197        }
198        catch ( IOException e )
199        {
200            // this should not happen
201            throw new RuntimeException( e );
202        }
203
204        this.sets = config.getList( "xsl:attribute-set[@name]" );
205        reset();
206    }
207
208    /**
209     * (Re-)initialize the AttributeSet.
210     */
211    private void reset()
212    {
213        this.attributeSet = new SimpleAttributeSet();
214    }
215
216}