![JAR search and dependency download from the Maven repository](/logo.png)
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 getTemplates() {
return (new ArrayList<>(this.templates.values()));
}
/**
*
* Adds a template.
*
*
* @param name
* The name.
* @param type
* The type.
* @param defaultValues
* The default values (optional).
* @param choices
* The choices (optional).
* @param descriptions
* The descriptions.
* @param context
* The context.
*/
public void addTemplate(String name, TemplateType type, Map defaultValues,
Map> choices, Map descriptions, Context context) {
Template template;
if (this.templates.containsKey(name)) {
context.addWarning(new TemplatesDuplicatedTemplateWarning(name));
} else {
template = new TemplateImpl(name, type, defaultValues, choices, descriptions);
this.templates.put(name, template);
}
}
}
/* **********************************************************************
* **********************************************************************
* **********************************************************************
* **********************************************************************
* **********************************************************************
*/
/**
*
* The template implementation of this class.
*
*
* @author Gerrit Hohl ([email protected])
* @version 1.0, 29.04.2016 by Gerrit Hohl
*/
private class TemplateImpl implements Template {
/** The name of the template. */
private String name;
/** The type. */
private TemplateType type;
/** The default values (optional). */
private Map defaultValues;
/** The choices (optional). */
private Map> choices;
/** The description. */
private Map descriptions;
/**
*
* Creates a template.
*
*
* @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 description.
*/
public TemplateImpl(String name, TemplateType type, Map defaultValues,
Map> choices, Map descriptions) {
super();
this.name = name;
this.type = type;
if (defaultValues == null) {
this.defaultValues = new LinkedHashMap<>();
} else {
this.defaultValues = new LinkedHashMap<>(defaultValues);
}
if (choices == null) {
this.choices = null;
} else {
this.choices = new LinkedHashMap<>();
for (Entry> entry : choices.entrySet()) {
this.choices.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
}
this.descriptions = new LinkedHashMap<>(descriptions);
}
@Override
public String getName() {
return this.name;
}
@Override
public TemplateType getType() {
return this.type;
}
@Override
public Map getDefaultValue() {
return this.defaultValues;
}
@Override
public Map> getChoices() {
return this.choices;
}
@Override
public Map getDescriptions() {
return this.descriptions;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy