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;
031import org.apache.maven.doxia.sink.impl.SinkUtils;
032import org.codehaus.plexus.util.ReaderFactory;
033
034/**
035 * A utility class to construct FO configuration parameters.
036 *
037 * @author ltheussl
038 * @version $Id$
039 * @since 1.1
040 */
041public class FoConfiguration
042{
043    /** Holds the single attributes. */
044    private MutableAttributeSet attributeSet;
045
046    /** The configuration instance. */
047    private final XMLConfiguration config;
048
049    /** The list of attribute sets. */
050    private List<?> sets;
051
052    /**
053     * Constructor.
054     */
055    public FoConfiguration()
056    {
057        this.config = new XMLConfiguration();
058
059        // necessary because some attributes contain commas:
060        config.setDelimiterParsingDisabled( true );
061
062        loadDefaultConfig();
063    }
064
065    /**
066     * Load configuration parameters from a File.
067     *
068     * @param configFile the configuration file.
069     *
070     * @throws java.io.IOException if the File cannot be read
071     *  or some error occurs when initializing the configuration parameters.
072     *
073     * @since 1.1.1
074     */
075    public void load( File configFile )
076            throws IOException
077    {
078        config.clear();
079
080        try
081        {
082            config.load( configFile );
083        }
084        catch ( ConfigurationException cex )
085        {
086            IOException ioe = new IOException();
087            ioe.initCause( cex );
088            throw ioe;
089        }
090
091        loadDefaultConfig(); // this adds default values that are missing from above
092    }
093
094    /**
095     * Builds a list of attributes.
096     *
097     * @param attributeId A unique id to identify the set of attributes.
098     * This should correspond to the name of an attribute-set
099     * defined in the configuration file.
100     * @return A string that contains a list of attributes with
101     * the values configured for the current builder. Returns the
102     * empty string if attributeId is null or if attributeId
103     * is not a valid identifier.
104     */
105    public String getAttributeString( String attributeId )
106    {
107        if ( attributeId == null )
108        {
109            return "";
110        }
111
112        reset();
113        addAttributes( attributeId );
114
115        return SinkUtils.getAttributeString( attributeSet );
116    }
117
118    /**
119     * Builds a set of attributes.
120     *
121     * @param attributeId A unique id to identify the set of attributes.
122     * This should correspond to the name of an attribute-set
123     * defined in the configuration file.
124     * @return A MutableAttributeSet that contains the attributes with
125     * the values configured for the current builder. Returns null
126     * if attributeId is null or empty, or if attributeId is not a valid identifier.
127     */
128    public MutableAttributeSet getAttributeSet( String attributeId )
129    {
130        if ( attributeId == null || attributeId.length() == 0 )
131        {
132            return null;
133        }
134
135        reset();
136        addAttributes( attributeId );
137
138        if ( attributeSet.getAttributeCount() == 0 )
139        {
140            return null;
141        }
142
143        return attributeSet;
144    }
145
146    /**
147     * Adds an attribute to the current StringBuilder.
148     *
149     * @param attributeId A unique id to identify the set of attributes.
150     * This should correspond to the name of an attribute-set
151     * defined in the configuration file.
152     */
153    private void addAttributes( String attributeId )
154    {
155        int index = sets.indexOf( attributeId );
156        String keybase = "xsl:attribute-set(" + String.valueOf( index ) + ")";
157
158        Object prop = config.getProperty( keybase + ".xsl:attribute" );
159
160        if ( prop instanceof List<?> )
161        {
162            List<?> values = (List<?>) prop;
163            List<?> keys = config.getList( keybase + ".xsl:attribute[@name]" );
164
165            for ( int i = 0; i < values.size(); i++ )
166            {
167                attributeSet.addAttribute( keys.get( i ), values.get( i ) );
168            }
169        }
170        else if ( prop instanceof String )
171        {
172            String value = config.getString( keybase + ".xsl:attribute" );
173            String key = config.getString( keybase + ".xsl:attribute[@name]" );
174            attributeSet.addAttribute( key, value );
175        }
176
177        String extend = config.getString( keybase + "[@use-attribute-sets]" );
178
179        if ( extend != null )
180        {
181            addAttributes( extend );
182        }
183    }
184
185    /** Load the default fo configuration file. */
186    private void loadDefaultConfig()
187    {
188        try
189        {
190            config.load( ReaderFactory.newXmlReader( getClass().getResourceAsStream( "/fo-styles.xslt" ) ) );
191        }
192        catch ( ConfigurationException cex )
193        {
194            // this should not happen
195            throw new RuntimeException( cex );
196        }
197        catch ( IOException e )
198        {
199            // this should not happen
200            throw new RuntimeException( e );
201        }
202
203        this.sets = config.getList( "xsl:attribute-set[@name]" );
204        reset();
205    }
206
207    /**
208     * (Re-)initialize the AttributeSet.
209     */
210    private void reset()
211    {
212        this.attributeSet = new SimpleAttributeSet();
213    }
214
215}