/*
 * @(#)ParserImplTableBase.java	1.8 05/11/17
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.sun.corba.se.spi.orb ;

import java.util.Map ;
import java.util.AbstractMap ;
import java.util.Set ;
import java.util.AbstractSet ;
import java.util.Iterator ;
import java.util.Properties ;

import java.lang.reflect.Field ;

import org.omg.CORBA.INTERNAL ;

// XXX This could probably be further extended by using more reflection and
// a dynamic proxy that satisfies the interfaces that are inherited by the
// more derived class.  Do we want to go that far?
public abstract class ParserImplTableBase extends ParserImplBase {
    private final ParserData[] entries ;

    public ParserImplTableBase( ParserData[] entries ) 
    {
	this.entries = entries ;
	setDefaultValues() ;
    }

    protected PropertyParser makeParser()
    {
	PropertyParser result = new PropertyParser() ;
	for (int ctr=0; ctr<entries.length; ctr++ ) {
	    ParserData entry = entries[ctr] ;
	    entry.addToParser( result ) ;
	}

	return result ;
    }

    private static final class MapEntry implements Map.Entry {
	private Object key ;
	private Object value ;

	public MapEntry( Object key )
	{
	    this.key = key ;
	}

	public Object getKey()
	{
	    return key ;
	}

	public Object getValue()
	{
	    return value ;
	}

	public Object setValue( Object value ) 
	{
	    Object result = this.value ;
	    this.value = value ;
	    return result ;
	}

	public boolean equals( Object obj )
	{
	    if (!(obj instanceof MapEntry))
		return false ;

	    MapEntry other = (MapEntry)obj ;

	    return (key.equals( other.key )) && 
		(value.equals( other.value )) ;
	}

	public int hashCode()
	{
	    return key.hashCode() ^ value.hashCode() ;
	}
    }

    // Construct a map that maps field names to test or default values,
    // then use setFields from the parent class.  A map is constructed
    // by implementing AbstractMap, which requires implementing the
    // entrySet() method, which requires implementing a set of
    // map entries, which requires implementing an iterator,
    // which iterates over the ParserData, extracting the
    // correct (key, value) pairs (nested typed lambda expression).
    private static class FieldMap extends AbstractMap {
	private final ParserData[] entries ;
	private final boolean useDefault ;

	public FieldMap( ParserData[] entries, boolean useDefault )
	{
	    this.entries = entries ;
	    this.useDefault = useDefault ;
	}

	public Set entrySet() 
	{
	    return new AbstractSet() 
	    {
		public Iterator iterator() 
		{
		    return new Iterator() {
			// index of next element to return
			int ctr = 0 ;

			public boolean hasNext() 
			{
			    return ctr < entries.length ;
			}

			public Object next() 
			{
			    ParserData pd = entries[ctr++] ;
			    Map.Entry result = new MapEntry( pd.getFieldName() ) ;
			    if (useDefault)
				result.setValue( pd.getDefaultValue() ) ;
			    else
				result.setValue( pd.getTestValue() ) ;
			    return result ;
			}

			public void remove()
			{
			    throw new UnsupportedOperationException() ;
			}
		    } ;
		}

		public int size() 
		{
		    return entries.length ;
		}
	    } ;
	}
    } ;

    protected void setDefaultValues()
    {
	Map map = new FieldMap( entries, true ) ;
	setFields( map ) ;	
    }

    public void setTestValues()
    {
	Map map = new FieldMap( entries, false ) ;
	setFields( map ) ;	
    }
}
