All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.javadpkg.impl.TemplatesParserImpl Maven / Gradle / Ivy

/*
 * dpkg - Debian Package library and the Debian Package Maven plugin
 * (c) Copyright 2016 Gerrit Hohl
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package net.sourceforge.javadpkg.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.sourceforge.javadpkg.Context;
import net.sourceforge.javadpkg.ParseException;
import net.sourceforge.javadpkg.Template;
import net.sourceforge.javadpkg.TemplateType;
import net.sourceforge.javadpkg.TemplateTypeParser;
import net.sourceforge.javadpkg.Templates;
import net.sourceforge.javadpkg.TemplatesConstants;
import net.sourceforge.javadpkg.TemplatesParser;
import net.sourceforge.javadpkg.control.Description;
import net.sourceforge.javadpkg.control.DescriptionParser;
import net.sourceforge.javadpkg.control.impl.DescriptionParserImpl;
import net.sourceforge.javadpkg.field.Field;
import net.sourceforge.javadpkg.field.FieldParser;
import net.sourceforge.javadpkg.field.impl.FieldParserImpl;
import net.sourceforge.javadpkg.io.DataSource;
import net.sourceforge.javadpkg.io.impl.DataStreamSource;

import java.util.Set;


/**
 * 

* A {@link TemplatesParser} implementation. *

* * @author Gerrit Hohl ([email protected]) * @version 1.0, 03.01.2016 by Gerrit Hohl */ public class TemplatesParserImpl implements TemplatesParser, TemplatesConstants { /** The parser for the fields. */ private FieldParser fieldParser; /** The parser for the template type. */ private TemplateTypeParser templateTypeParser; /** The description parser. */ private DescriptionParser descriptionParser; /** *

* Creates a parser. *

*/ public TemplatesParserImpl() { super(); this.fieldParser = new FieldParserImpl(true, true, false); this.templateTypeParser = new TemplateTypeParserImpl(); this.descriptionParser = new DescriptionParserImpl(); } @Override public Templates parseTemplates(String value, Context context) throws ParseException { Templates templates; List fields; if (value == null) throw new IllegalArgumentException("Argument value is null."); if (context == null) throw new IllegalArgumentException("Argument context is null."); // --- Get the fields from the value --- try { try (DataSource source = new DataStreamSource(new ByteArrayInputStream(value.getBytes(UTF_8)), "templates", false)) { fields = this.parseFields(source, context); } } catch (IOException | UnsupportedCharsetException e) { throw new ParseException("Couldn't parse fields of templates: " + e.getMessage(), e); } // --- Get the templates from the fields --- templates = this.parseTemplates(fields, context); return templates; } @Override public Templates parseTemplates(DataSource source, Context context) throws IOException, ParseException { Templates templates; List fields; if (source == null) throw new IllegalArgumentException("Argument source is null."); if (context == null) throw new IllegalArgumentException("Argument context is null."); // --- Get the fields from the source --- fields = this.parseFields(source, context); // --- Get the templates from the fields --- templates = this.parseTemplates(fields, context); return templates; } /** *

* Parses the fields from the source. *

* * @param source * The source. * @param context * The context. * @return The fields. * @throws IOException * If an I/O error occurs. * @throws ParseException * If an error occurs while parsing the fields. */ private List parseFields(DataSource source, Context context) throws IOException, ParseException { List fields; try { fields = this.fieldParser.parseFieldsAsList(source, context); } catch (IOException e) { throw new IOException("Couldn't parse fields of templates: " + e.getMessage(), e); } catch (ParseException e) { throw new ParseException("Couldn't parse fields of templates: " + e.getMessage(), e); } return fields; } /** *

* Parses the templates from the specified fields. *

* * @param fields * The fields. * @param context * The context. * @return The templates. * @throws ParseException * If an error occurs while parsing the fields. */ private Templates parseTemplates(List fields, Context context) throws ParseException { TemplatesImpl templates; Set unsupportedFieldNames; String name = null; TemplateType type = null; Map defaultValues = null; Map> choices = null; Map descriptions = null; templates = new TemplatesImpl(); unsupportedFieldNames = new LinkedHashSet<>(); try { for (Field field : fields) { if (field.isEmpty()) { if (name != null) { this.addTemplate(context, templates, name, type, defaultValues, choices, descriptions); } name = null; type = null; defaultValues = null; choices = null; descriptions = null; } else if (FIELD_TEMPLATE.equals(field.getName())) { if (name != null) throw new ParseException("Found template |" + field.getValue() + "| without an empty line between it and the previous template |" + name + "|."); // this.addTemplate(context, templates, name, type, defaultValues, choices, descriptions); type = null; defaultValues = null; choices = null; descriptions = null; /* * TODO Parse the template name * https://www.debian.org/doc/packaging-manuals/debconf_specification.html#AEN49 */ name = field.getValue(); } else { if (name == null) throw new ParseException( "Found the field |" + field.getName() + "| without any corresponding template."); if (FIELD_TYPE.equals(field.getName())) { if (type != null) throw new ParseException("The field |" + field.getName() + "| exists more the one time in the template |" + name + "|."); try { type = this.templateTypeParser.parseTemplateType(field.getValue(), context); } catch (ParseException e) { throw new ParseException("Couldn't parse field |" + field.getName() + "| in the template |" + name + "|: " + e.getMessage(), e); } } else if (FIELD_DEFAULT.equals(field.getName()) || field.getName().startsWith(FIELD_DEFAULT_PREFIX)) { try { defaultValues = this.parseDefaultValue(defaultValues, field); } catch (ParseException e) { throw new ParseException("Couldn't parse field |" + field.getName() + "| in the template |" + name + "|: " + e.getMessage(), e); } } else if (FIELD_CHOICES.equals(field.getName()) || field.getName().startsWith(FIELD_CHOICES_PREFIX)) { try { choices = this.parseChoices(context, choices, field); } catch (ParseException e) { throw new ParseException("Couldn't parse field |" + field.getName() + "| in the template |" + name + "|: " + e.getMessage(), e); } } else if (FIELD_DESCRIPTION.equals(field.getName()) || field.getName().startsWith(FIELD_DESCRIPTION_PREFIX)) { try { descriptions = this.parseDescription(context, descriptions, field); } catch (ParseException e) { throw new ParseException("Couldn't parse field |" + field.getName() + "| in the template |" + name + "|: " + e.getMessage(), e); } } else { if (!unsupportedFieldNames.contains(field.getName())) { context.addWarning(new TemplatesUnsupportFieldNameWarning(field.getName())); unsupportedFieldNames.add(field.getName()); } } } } // --- Do we still have a pending template? --- if (name != null) { this.addTemplate(context, templates, name, type, defaultValues, choices, descriptions); } } catch (ParseException e) { throw new ParseException("Couldn't parse templates: " + e.getMessage(), e); } return templates; } /** *

* Adds a template. *

* * @param context * The context. * @param templates * The templates. * @param name * The name of the template. * @param type * The type. * @param defaultValues * The default values (optional). * @param choices * The choices (optional). * @param descriptions * The descriptions. * @throws ParseException * If a needed property is missing. */ private void addTemplate(Context context, TemplatesImpl templates, String name, TemplateType type, Map defaultValues, Map> choices, Map descriptions) throws ParseException { Set missingFieldNames; missingFieldNames = new LinkedHashSet<>(); // --- Do we have all needed fields? --- if (type == null) { missingFieldNames.add(FIELD_TYPE); } if ((this.templateTypeParser.getTypeSelect().equals(type) || this.templateTypeParser.getTypeMultiselect().equals(type)) && (choices == null)) { missingFieldNames.add(FIELD_CHOICES); } if ((descriptions == null) || !descriptions.containsKey("")) { context.addWarning(new TemplatesMissingFieldWarning(name, FIELD_DESCRIPTION)); descriptions = new HashMap<>(); } if (!missingFieldNames.isEmpty()) throw new ParseException( "Missing fields " + this.getFieldNamesAsString(missingFieldNames) + " for template |" + name + "|."); // --- Add template --- templates.addTemplate(name, type, defaultValues, choices, descriptions, context); } /** *

* Parses a default value field. *

* * @param defaultValues * The map containing the default values (optional). * @param field * The field. * @return The map containing the default values. * @throws ParseException * If an error occurs during the parsing. */ private Map parseDefaultValue(Map defaultValues, Field field) throws ParseException { Map map; String name, text; // --- Make sure that we have a map --- if (defaultValues == null) { map = new LinkedHashMap<>(); } else { map = defaultValues; } // --- Get the name --- name = field.getName(); if (FIELD_DEFAULT.equals(name)) { name = ""; } else { name = name.substring(8); if (!name.endsWith(UTF_8_SUFFIX)) throw new ParseException("Found description |" + field.getName() + "|, but currently only UTF-8 is supported."); } if (map.containsKey(name)) throw new ParseException( "The field |" + field.getName() + "| exists more the one time in the template |" + name + "|."); // --- Get the text --- text = field.getValue(); map.put(name, text); return map; } /** *

* Parses the choices. *

* * @param context * The context. * @param choices * The map containing the choices (optional). * @param field * The field. * @return The map containing the choices. * @throws ParseException * If an error occurs during the parsing. */ private Map> parseChoices(Context context, Map> choices, Field field) throws ParseException { Map> map; String name, value, choice; List values; String[] parts; if (choices == null) { map = new LinkedHashMap<>(); } else { map = choices; } // --- Get the name --- name = field.getName(); if (FIELD_CHOICES.equals(name)) { name = ""; } else { name = name.substring(8); if (!name.endsWith(UTF_8_SUFFIX)) { context.addWarning(new TemplatesUnsupportFieldNameWarning(field.getName())); return map; } } if (map.containsKey(name)) throw new ParseException( "The field |" + field.getName() + "| exists more the one time in the template |" + name + "|."); // --- Get the values --- value = field.getValue(); values = new ArrayList<>(); parts = value.split(","); for (String part : parts) { choice = part.trim(); values.add(choice); } map.put(name, values); return map; } /** *

* Parses a description field. *

* * @param context * The context. * @param descriptions * The map containing the descriptions (optional). * @param field * The field. * @return The map containing the descriptions. * @throws ParseException * If an error occurs during the parsing. */ private Map parseDescription(Context context, Map descriptions, Field field) throws ParseException { Map map; String name; Description description; // --- Make sure that we have a map --- if (descriptions == null) { map = new LinkedHashMap<>(); } else { map = descriptions; } // --- Get the name --- name = field.getName(); if (FIELD_DESCRIPTION.equals(name)) { name = ""; } else { name = name.substring(12); if (!name.endsWith(UTF_8_SUFFIX)) throw new ParseException("Found description |" + field.getName() + "|, but currently only UTF-8 is supported."); } if (map.containsKey(name)) throw new ParseException( "The field |" + field.getName() + "| exists more the one time in the template |" + name + "|."); // --- Get the text --- try { description = this.descriptionParser.parseDescription(field.getValue(), context); } catch (ParseException e) { throw new ParseException("Couldn't parse field |" + field.getName() + "|: " + e.getMessage(), e); } map.put(name, description); return map; } /** *

* Returns the field names from the specified set as {@link String}. *

* * @param fieldNames * The field names. * @return The {@link String} containing the field names. */ private String getFieldNamesAsString(Set fieldNames) { StringBuilder sb; sb = new StringBuilder(); for (String fieldName : fieldNames) { if (sb.length() > 0) { sb.append(", "); } sb.append('|'); sb.append(fieldName); sb.append('|'); } return sb.toString(); } /* ********************************************************************** * ********************************************************************** * ********************************************************************** * ********************************************************************** * ********************************************************************** */ /** *

* The {@link Templates} implementation of this class. *

* * @author Gerrit Hohl ([email protected]) * @version 1.0, 29.04.2016 by Gerrit Hohl */ private class TemplatesImpl implements Templates { /** The templates. */ private Map templates; /** *

* Creates the templates. *

*/ public TemplatesImpl() { super(); this.templates = new LinkedHashMap<>(); } @Override public List