001package jmri.jmrit.logixng;
002
003import java.util.*;
004import java.util.concurrent.CopyOnWriteArrayList;
005
006/**
007 * The category of expressions and actions.
008 * <P>
009 * It's used to group expressions or actions then the user creates a new
010 * expression or action.
011 * <P>
012 * This class is intended to be an Enum, but implemented as an abstract class
013 * to allow adding more categories later without needing to change this class.
014 * For example, external programs using JMRI as a lib might want to add their
015 * own categories.
016 * 
017 * @author Daniel Bergqvist Copyright 2018
018 */
019public abstract class Category implements Comparable<Category> {
020
021    /**
022     * A item on the layout, for example turnout, sensor and signal mast.
023     */
024    public static final Item ITEM = new Item();
025    
026    /**
027     * Common.
028     */
029    public static final Common COMMON = new Common();
030    
031    /**
032     * Other things.
033     */
034    public static final Other OTHER = new Other();
035    
036    /**
037     * Get all the registered Categories
038     * @return a list of categories
039     */
040    public static List<Category> values() {
041        if (_categories == null) {
042            synchronized(Category.class) {
043                if (_categories == null) {
044                    // It's not often any item is added to this list so we use CopyOnWriteArrayList
045                    _categories = new CopyOnWriteArrayList<>();
046                    registerCategory(ITEM);
047                    registerCategory(COMMON);
048                    registerCategory(OTHER);
049                }
050            }
051        }
052        return Collections.unmodifiableList(_categories);
053    }
054    
055    /**
056     * Register a category
057     * @param category the category
058     */
059    public static void registerCategory(Category category) {
060        // Ensure that the _categories variable is initialized
061        values();
062        
063        _categories.add(category);
064    }
065    
066    
067    private static volatile List<Category> _categories;
068    
069    private final String _name;
070    private final String _description;
071    private final int _order;
072    
073    
074    protected Category(String name, String description, int order) {
075        _name = name;
076        _description = description;
077        _order = order;
078    }
079    
080    public String name() {
081        return _name;
082    }
083    
084    @Override
085    public final String toString() {
086        return _description;
087    }
088    
089    public int order() {
090        return _order;
091    }
092    
093    @Override
094    public boolean equals(Object o) {
095        if (o instanceof Category) {
096            Category c = (Category)o;
097            return _description.equals(c._description) && _name.equals(c._name);
098        }
099        return false;
100    }
101    
102    @Override
103    public int hashCode() {
104        return _description.hashCode();
105    }
106    
107    @Override
108    public int compareTo(Category c) {
109        if (_order < c.order()) return -1;
110        if (_order > c.order()) return 1;
111        return 0;
112    }
113    
114    
115    public static final class Item extends Category {
116
117        public Item() {
118            super("ITEM", Bundle.getMessage("CategoryItem"), 100);
119        }
120    }
121    
122    
123    public static final class Common extends Category {
124
125        public Common() {
126            super("COMMON", Bundle.getMessage("CategoryCommon"), 200);
127        }
128    }
129    
130    
131    public static final class Other extends Category {
132
133        public Other() {
134            super("OTHER", Bundle.getMessage("CategoryOther"), 300);
135        }
136    }
137    
138}