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

com.dyuproject.protostuff.parser.EnumGroup Maven / Gradle / Ivy

The newest version!
//========================================================================
//Copyright 2007-2009 David Yu [email protected]
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at 
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================

package com.dyuproject.protostuff.parser;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;

/**
 * Represents an enum declared in either the {@link Proto} or nested in a {@link Message}.
 *
 * @author David Yu
 * @created Dec 21, 2009
 */
public class EnumGroup extends AnnotationContainer implements HasName, HasOptions
{
    
    /**
     * Disabled by default (the earlier protoc 2.x versions enabled this by default, but 
     * was changed later on).
     */
    public static final boolean ENUM_ALLOW_ALIAS = Boolean.parseBoolean(
            "protostuff.enum_allow_alias");
    
    final String name;
    final Message parentMessage;
    final Proto proto;
    
    final LinkedHashMap values = new LinkedHashMap();
    final ArrayList sortedValues = new ArrayList();
    final LinkedHashMap standardOptions = new LinkedHashMap();
    final LinkedHashMap extraOptions = new LinkedHashMap();
    
    private ArrayList indexedValues;
    private ArrayList uniqueSortedValues;
    
    public EnumGroup(String name, Message parentMessage, Proto proto)
    {
        this.name = name;
        this.parentMessage = parentMessage;
        
        if(parentMessage != null)
        {
            this.proto = parentMessage.getProto();
            parentMessage.addNestedEnumGroup(this);
        }
        else
        {
            this.proto = proto;
            proto.addEnumGroup(this);
        }
    }
    
    public String getName()
    {
        return name;
    }
    
    public String getFullName()
    {
        StringBuilder buffer = new StringBuilder();
        if(isNested())
            buffer.append(parentMessage.getFullName()).append('.').append(name);
        else
            buffer.append(getProto().getPackageName()).append('.').append(name);
        return buffer.toString();
    }
    
    public String getJavaFullName()
    {
        StringBuilder buffer = new StringBuilder();
        if(isNested())
            buffer.append(parentMessage.getJavaFullName()).append('.').append(name);
        else
            buffer.append(getProto().getJavaPackageName()).append('.').append(name);
        return buffer.toString();
    }
    
    public String getRelativeName()
    {
        return isNested() ? parentMessage.getRelativeName() + "." + name : name;
    }
    
    /* ================================================== */
    
    public Message getParentMessage()
    {
        return parentMessage;
    }
    
    public boolean isNested()
    {
        return parentMessage != null;
    }
    
    public Proto getProto()
    {
        return proto;
    }
    
    /* ================================================== */
    
    public void putStandardOption(String key, Object value)
    {
        putExtraOption(key, value);
        standardOptions.put(key, value);
    }
    
    public void putExtraOption(String key, Object value)
    {
        if(extraOptions.put(key, value) != null)
            throw err("Duplicate enum option: " + key, getProto());
    }
    
    public LinkedHashMap getStandardOptions()
    {
        return standardOptions;
    }
    
    public Object getStandardOption(String key)
    {
        return standardOptions.get(key);
    }
    
    public LinkedHashMap getExtraOptions()
    {
        return extraOptions;
    }
    
    public LinkedHashMap getO()
    {
        return getOptions();
    }
    
    public LinkedHashMap getOptions()
    {
        return extraOptions;
    }
    
    @SuppressWarnings("unchecked")
    public  V getExtraOption(java.lang.String key)
    {
        return (V)extraOptions.get(key);
    }
    
    public Value getValue(int index)
    {
        if(indexedValues == null)
            indexedValues = new ArrayList(values.values());
        
        return indexedValues.get(index);
    }
    
    public Value getValue(String name)
    {
        return values.get(name);
    }
    
    public Collection getValues()
    {
        return values.values();
    }
    
    public LinkedHashMap getValueMap()
    {
        return values;
    }
    
    public ArrayList getSortedValues()
    {
        return sortedValues;
    }
    
    public Value getFirstValue()
    {
        if(indexedValues == null)
            indexedValues = new ArrayList(values.values());
        
        return indexedValues.get(0);
    }
    
    public int getValueCount()
    {
        return values.size();
    }
    
    void add(Value value)
    {
        if(values.put(value.name, value) != null)
        {
            throw err("The enum " + name + " has duplicate names: " + value.name, 
                    getProto());
        }
        
        sortedValues.add(value);
    }
    
    void cacheFullyQualifiedName()
    {
        final Boolean b = (Boolean)getOptions().get("allow_alias");
        if(b != null)
        {
            if(b.booleanValue())
                Collections.sort(sortedValues);
            else
                Collections.sort(sortedValues, Value.NO_ALIAS_COMPARATOR);
        }
        else if(ENUM_ALLOW_ALIAS)
            Collections.sort(sortedValues);
        else
            Collections.sort(sortedValues, Value.NO_ALIAS_COMPARATOR);
        
        final Proto proto = getProto();
        final String fullName = getFullName();
        
        proto.fullyQualifiedEnumGroups.put(fullName, this);
        
        if(!standardOptions.isEmpty())
            proto.references.add(new ConfiguredReference(standardOptions, extraOptions, fullName));
        
        for(Value v : values.values())
        {
            if(!v.field.standardOptions.isEmpty())
            {
                proto.references.add(new ConfiguredReference(
                        v.field.standardOptions, v.field.extraOptions, fullName));
            }
        }
    }
    
    public ArrayList getUniqueSortedValues()
    {
        if(uniqueSortedValues != null)
            return uniqueSortedValues;
        
        uniqueSortedValues = new ArrayList();
        Value last = null;
        for(Value v : sortedValues)
        {
            if(last==null || v.number!=last.number)
                uniqueSortedValues.add(v);
            last = v;
        }
        return uniqueSortedValues;
    }
    
    public String toString()
    {
        return new StringBuilder()
            .append('{')
            .append("name:").append(name)
            .append(',').append("values:").append(values)
            .append('}')
            .toString();
    }

    public static class Value extends AnnotationContainer implements Comparable, HasName
    {
        public static final Comparator NO_ALIAS_COMPARATOR = 
                new Comparator()
        {
            public int compare(Value v1, Value v2)
            {
                if(v1.number == v2.number)
                {
                    throw err("The enum value " + 
                            v2.enumGroup.getName() + "." + v2.getName() + 
                            " cannot have the same number as " + 
                            v1.enumGroup.getName() + "." + v1.getName(), 
                            v2.enumGroup.getProto());
                }
                
                return v1.number - v2.number;
            }
        };
        
        final String name;
        final int number;
        final EnumGroup enumGroup;
        
        public final EnumField field = new EnumField(this);

        public Value(String name, int number, EnumGroup enumGroup)
        {
            this.name = name;
            this.number = number;
            this.enumGroup = enumGroup;
            
            field.enumGroup = enumGroup;
            field.name = name;
            
            enumGroup.add(this);
        }

        /**
         * @return the name
         */
        public String getName()
        {
            return name;
        }

        /**
         * @return the number
         */
        public int getNumber()
        {
            return number;
        }
        
        public Proto getProto()
        {
            return enumGroup.getProto();
        }
        
        /**
         * @return the enumGroup
         */
        public EnumGroup getEnumGroup()
        {
            return enumGroup;
        }
        
        /**
         * Alias to {@link #getEnumGroup()}.
         */
        public EnumGroup getEg()
        {
            return enumGroup;
        }
        
        // options
        
        public LinkedHashMap getStandardOptions()
        {
            return field.getStandardOptions();
        }
        
        public LinkedHashMap getExtraOptions()
        {
            return field.getExtraOptions();
        }
        
        public LinkedHashMap getO()
        {
            return getOptions();
        }
        
        /**
         * Returns the options configured.
         */
        public LinkedHashMap getOptions()
        {
            return field.getOptions();
        }

        public String toString()
        {
            return new StringBuilder().append(name).append(':').append(number).toString();
        }

        public int compareTo(Value o)
        {
            // if equal, sort by order of declaration
            return number - o.number;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy