Лучшая практика для документирования доступного/необходимого содержания файла свойств Java

Это должно сделать работу (проверено на Bokeh v1.0.4). Вы можете изменить ориентацию легенды на «вертикальную», если хотите.

from bokeh.core.properties import value
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource, HoverTool, CustomJS
from bokeh.plotting import figure
from bokeh.transform import dodge
from bokeh.palettes import Spectral6

data = {'FFCB' : ['D', 'I'],
        'CS'   : [0.013254, 0.01],
        'FPSI'   : [0.00264871, 0.02],
        'SA'   : [0.03, 0.114216],
        'NA'   : [0.0127895, 0.00567031],
        'O'   : [0.00552444, 0.03],
        'FPSDA'   : [0.00136219, 0.04],
        'HDR'   : [0.03, 0.05]}

source = ColumnDataSource(data = data)

p = figure(x_range = data['FFCB'], y_range = (0, 0.2), plot_width = 600, plot_height = 400, title = "Clustered bar chart", tools = '')

vbar1 = p.vbar(x = dodge('FFCB', -0.25, range = p.x_range), top = 'CS', width = 0.1, source = source,
       color = Spectral6[0], legend = value("CS"))
hover_tool_vbar1 = HoverTool(tooltips = [('CS', '@CS{0.000}')], show_arrow = False, renderers = [vbar1])

vbar2 = p.vbar(x = dodge('FFCB', -0.15, range = p.x_range), top = 'FPSI', width = 0.1, source = source,
       color = Spectral6[1], legend = value("FPSI"))
hover_tool_vbar2 = HoverTool(tooltips = [('FPSI', '@FPSI{0.000}')], show_arrow = False, renderers = [vbar2])

vbar3 = p.vbar(x = dodge('FFCB', -0.05, range = p.x_range), top = 'SA', width = 0.1, source = source,
       color = Spectral6[2], legend = value("SA"))
hover_tool_vbar3 = HoverTool(tooltips = [('SA', '@SA{0.000}')], show_arrow = False, renderers = [vbar3])

vbar4 = p.vbar(x = dodge('FFCB', 0.05, range = p.x_range), top = 'NA', width = 0.1, source = source,
       color = Spectral6[3], legend = value("NA"))
hover_tool_vbar4 = HoverTool(tooltips = [('NA', '@NA{0.000}')], show_arrow = False, renderers = [vbar4])

vbar5 = p.vbar(x = dodge('FFCB', 0.15, range = p.x_range), top = 'O', width = 0.1, source = source,
       color = Spectral6[4], legend = value("O"))
hover_tool_vbar5 = HoverTool(tooltips = [('O', '@O{0.000}')], show_arrow = False, renderers = [vbar5])

vbar6 = p.vbar(x = dodge('FFCB', 0.25, range = p.x_range), top = 'HDR', width = 0.1, source = source,
       color = Spectral6[5], legend = value("HDR"))
hover_tool_vbar6 = HoverTool(tooltips = [('HDR', '@HDR{0.000}')], show_arrow = False, renderers = [vbar6])

p.x_range.range_padding = 0.2
p.xgrid.grid_line_color = None
p.legend.location = "top_left"
p.legend.click_policy = 'hide'
p.legend.orientation = "horizontal"

p.add_tools(hover_tool_vbar1, hover_tool_vbar2, hover_tool_vbar3, hover_tool_vbar4, hover_tool_vbar5, hover_tool_vbar6)

show(p)

Результат:

enter image description here

6
задан Community 23 May 2017 в 12:09
поделиться

3 ответа

Я никогда не видел стандартного способа сделать это. Вероятно, я бы сделал:

  • обернуть или расширить java.util.Properties class
  • переопределить (продлить) или предоставить метод (если обернуть) метод store (или storeToXML и т. Д.) ), который записывает комментарий для каждой строки. У
  • есть метод, который хранит свойства, есть своего рода входной файл, в котором вы описываете свойства каждого из них.

Это не дает вам ничего, что вы делаете вручную, за исключением того, что вы можете управлять информацией другим способом, с которым вам будет проще иметь дело - например, у вас может быть программа, которая выкладывает комментарии для чтения. Это потенциально даст вам программный доступ, который вам нужен, но это нечто само собой разумеющееся.

Или это может быть слишком много работы, чтобы получить слишком мало (именно поэтому там нет ничего очевидного).

Если вы можете указать вид комментариев, которые вы хотите видеть, я мог бы сделать удар писать что-то, если мне скучно :-) (это то, что я люблю делать для развлечения, больной, я знаю: -).

Хорошо ... Мне стало скучно ... вот что-то хотя бы начало: -)

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;


public class PropertiesVerifier
{
    private final Map<String, PropertyInfo> optionalInfo;
    private final Map<String, PropertyInfo> requiredInfo;

    {
        optionalInfo = new HashMap<String, PropertyInfo>();
        requiredInfo = new HashMap<String, PropertyInfo>();
    }

    public PropertiesVerifier(final PropertyInfo[] infos)
    {
        for(final PropertyInfo info : infos)
        {
            final Map<String, PropertyInfo> infoMap;

            if(info.isRequired())
            {
                infoMap = requiredInfo;
            }
            else
            {
                infoMap = optionalInfo;
            }

            infoMap.put(info.getName(), info);
        }
    }

    public void verifyProperties(final Properties properties)
    {
        for(final Entry<Object, Object> property : properties.entrySet())      
        {
            final String key;
            final String value;

            key   = (String)property.getKey();
            value = (String)property.getValue();

            if(!(isValid(key, value)))
            {
                throw new IllegalArgumentException(value + " is not valid for: " + key);
            }
        }
    }

    public boolean isRequired(final String key)
    {
        return (requiredInfo.get(key) != null);
    }

    public boolean isOptional(final String key)
    {
        return (optionalInfo.get(key) != null);
    }

    public boolean isKnown(final String key)
    {
        return (isRequired(key) || isOptional(key));
    }

    public Class getType(final String key)
    {
        final PropertyInfo info;

        info = getPropertyInfoFor(key);

        return (info.getType());
    }

    public boolean isValid(final String key,
                           final String value)
    {
        final PropertyInfo info;

        info = getPropertyInfoFor(key);

        return (info.verify(value));
    }

    private PropertyInfo getPropertyInfoFor(final String key)
    {
        PropertyInfo info;

        info = requiredInfo.get(key);

        if(info == null)
        {
            info = optionalInfo.get(key);

            if(info == null)
            {
                // should be a better exception maybe... depends on how you 
                // want to deal with it
                throw new IllegalArgumentException(key + " 
                                                   is not a valid property name");
            }
        }

        return (info);
    }

    protected final static class PropertyInfo
    {
        private final String name;
        private final boolean required;
        private final Class clazz;
        private final Verifier verifier;

        protected PropertyInfo(final String   nm,
                               final boolean  mandatory,
                               final Class    c)
        {
            this(nm, mandatory, c, getDefaultVerifier(c));
        }

        protected PropertyInfo(final String   nm,
                               final boolean  mandatory,
                               final Class    c,
                               final Verifier v)
        {
            // check for null
            name     = nm;
            required = mandatory;
            clazz    = c;
            verifier = v;
        }

        @Override
        public int hashCode()
        {
            return (getName().hashCode());
        }

        @Override
        public boolean equals(final Object o)
        {
            final boolean retVal;

            if(o instanceof PropertyInfo)
            {
                final PropertyInfo other;

                other  = (PropertyInfo)o;
                retVal = getName().equals(other.getName());
            }
            else
            {
                retVal = false;
            }

            return (retVal);
        }

        public boolean verify(final String value)
        {
            return (verifier.verify(value));
        }

        public String getName()
        {
            return (name);
        }

        public boolean isRequired()
        {
            return (required);
        }

        public Class getType()
        {
            return (clazz);
        }
    }

    private static Verifier getDefaultVerifier(final Class clazz)
    {
        final Verifier verifier;

        if(clazz.equals(Boolean.class))
        {
            // shoudl use a singleton to save space...
            verifier = new BooleanVerifier();
        }
        else
        {
            throw new IllegalArgumentException("Unknown property type: " + 
                                               clazz.getCanonicalName());
        }

        return (verifier);
    }

    public static interface Verifier
    {
        boolean verify(final String value);
    }

    public static class BooleanVerifier
        implements Verifier
    {
        public boolean verify(final String value)
        {
            final boolean retVal;

            if(value.equalsIgnoreCase("true") ||
               value.equalsIgnoreCase("false"))
            {
                retVal = true;
            }
            else
            {
                retVal = false;
            }

            return (retVal);
        }
    }
}

И простой тест для него:

import java.util.Properties;


public class Main
{
    public static void main(String[] args)
    {
        final Properties         properties;
        final PropertiesVerifier verifier;

        properties = new Properties();
        properties.put("property.one",   "true");
        properties.put("property.two",   "false");
//        properties.put("property.three", "5");
        verifier = new PropertiesVerifier(
            new PropertiesVerifier.PropertyInfo[]
            {
                new PropertiesVerifier.PropertyInfo("property.one",   
                                                    true, 
                                                    Boolean.class),
                new PropertiesVerifier.PropertyInfo("property.two",   
                                                    false, 
                                                    Boolean.class),
//                new PropertiesVerifier.PropertyInfo("property.three", 
//                                                    true, 
//                                                    Boolean.class),
            });

        System.out.println(verifier.isKnown("property.one"));
        System.out.println(verifier.isKnown("property.two"));
        System.out.println(verifier.isKnown("property.three"));

        System.out.println(verifier.isRequired("property.one"));
        System.out.println(verifier.isRequired("property.two"));
        System.out.println(verifier.isRequired("property.three"));

        System.out.println(verifier.isOptional("property.one"));
        System.out.println(verifier.isOptional("property.two"));
        System.out.println(verifier.isOptional("property.three"));

        System.out.println(verifier.getType("property.one"));
        System.out.println(verifier.getType("property.two"));

        // System.out.println(verifier.getType("property.tthree"));
        System.out.println(verifier.isValid("property.one", "true"));
        System.out.println(verifier.isValid("property.two", "false"));
        // System.out.println(verifier.isValid("property.tthree", "5"));


        verifier.verifyProperties(properties);
    }
}
1
ответ дан 17 December 2019 в 00:14
поделиться

Вы можете использовать некоторые функции пакета Apache Commons Configuration . По крайней мере, он обеспечивает тип доступа к вашим свойствам.

В традиционном файле свойств Java есть только соглашения. Некоторые из них, которые я видел, включают, как вы сказали, пример файла свойств. Другой способ заключается в предоставлении конфигурации по умолчанию со всеми свойствами, но закомментированной.

Если вы действительно хотите что-то требовать, возможно, вы не ищете файл свойств. Вы можете использовать файл конфигурации XML и указать схему с типами данных и требованиями. Вы можете использовать jaxb, чтобы скомпилировать схему в java и прочитать ее таким образом. С помощью проверки вы можете убедиться, что необходимые свойства есть.

Лучшее, на что вы можете надеяться, это когда вы выполняете приложение, оно читает, анализирует, и проверяет свойства в файле. Если вам абсолютно необходимо оставаться на основе свойств и не хотите переходить на xml, но вам нужен этот анализ. У вас может быть файл вторичных свойств, в котором перечислены все свойства, которые могут быть включены, его тип и необходимость в нем. Затем вам нужно написать валидатор файла свойств, который будет принимать файл для проверки, а также файл свойств, подобный схеме валидации. Что-то вроде

#list of required properties
required=prop1,prop2,prop3

#all properties and their types
prop1.type=Integer
prop2.type=String

Я не просмотрел весь пакет конфигурации Apache, но у них часто бывают полезные утилиты, подобные этой. Я не удивлюсь, если вы найдете там что-нибудь, что упростит это.

У вас может быть файл вторичных свойств, в котором перечислены все свойства, которые могут быть включены, его тип и необходимость в нем. Затем вам нужно написать валидатор файла свойств, который будет принимать файл для проверки, а также файл свойств, подобный схеме валидации. Что-то вроде

#list of required properties
required=prop1,prop2,prop3

#all properties and their types
prop1.type=Integer
prop2.type=String

Я не просмотрел весь пакет конфигурации Apache, но у них часто бывают полезные утилиты, подобные этой. Я не удивлюсь, если вы найдете там что-нибудь, что упростит это.

У вас может быть файл вторичных свойств, в котором перечислены все свойства, которые могут быть включены, его тип и необходимость в нем. Затем вам нужно написать валидатор файла свойств, который будет принимать файл для проверки, а также файл свойств, подобный схеме валидации. Что-то вроде

#list of required properties
required=prop1,prop2,prop3

#all properties and their types
prop1.type=Integer
prop2.type=String

Я не просмотрел весь пакет конфигурации Apache, но у них часто бывают полезные утилиты, подобные этой. Я не удивлюсь, если вы найдете там что-нибудь, что упростит это.

но они часто имеют полезные утилиты, как это. Я не удивлюсь, если вы найдете там что-нибудь, что упростит это.

но они часто имеют полезные утилиты, как это. Я не удивлюсь, если вы найдете там что-нибудь, что упростит это.

3
ответ дан 17 December 2019 в 00:14
поделиться

Одним из простых способов является распространение вашего проекта с файлом примера свойств, например, мой проект в svn a "build. properties.example ", со свойствами, прокомментированными при необходимости. Локально правильные свойства не входят в SVN.

Так как вы упоминаете «getopt», мне интересно, вы действительно думаете о строковых аргументах cmd? Если есть «main», которому нужны специфические свойства, я обычно помещаю соответствующие инструкции в сообщение «useage», которое выводит, если аргументы неверны или «-h».

1
ответ дан 17 December 2019 в 00:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: