/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.trinidadbuild.plugin.faces.parse;

import java.net.URL;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Logger;


/**
 * FacesConfigBean is a Java representation of the faces-config XML element.
 */
public class FacesConfigBean extends ObjectBean
{
  /**
   * Adds a converter to this faces config document.
   *
   * @param converter  the converter to add
   */
  public void addConverter(
    ConverterBean converter)
  {
    converter.attach(this);
    if (converter.hasConverterId())
      _converters.put(converter.getConverterId(), converter);
  }

  /**
   * Returns the converter for this converter type.
   *
   * @param converterId  the converter type to find
   */
  public ConverterBean findConverter(
    String converterId)
  {
    return _converters.get(converterId);
  }

  /**
   * Returns true if this faces config has any converters.
   *
   * @return true  if this faces config has any converters,
   *         otherwise false
   */
  public boolean hasConverters()
  {
    return !_converters.isEmpty();
  }

  /**
   * Returns an iterator for all converters in this faces
   * config.
   *
   * @return  the converter iterator
   */
  public Iterator<ConverterBean> converters()
  {
    return _converters.values().iterator();
  }

  /**
   * Adds a validator to this faces config document.
   *
   * @param validator  the validator to add
   */
  public void addValidator(
    ValidatorBean validator)
  {
    validator.attach(this);
    if (validator.hasValidatorId())
      _validators.put(validator.getValidatorId(), validator);
  }

  /**
   * Returns the validator for this validator type.
   *
   * @param validatorId  the validator type to find
   */
  public ValidatorBean findValidator(
    String validatorId)
  {
    return _validators.get(validatorId);
  }

  /**
   * Returns true if this faces config has any validators.
   *
   * @return true  if this faces config has any validators,
   *         otherwise false
   */
  public boolean hasValidators()
  {
    return !_validators.isEmpty();
  }

  /**
   * Returns an iterator for all validators in this faces
   * config.
   *
   * @return  the validator iterator
   */
  public Iterator<ValidatorBean> validators()
  {
    return _validators.values().iterator();
  }

  /**
   * Adds a component to this faces config document.
   *
   * @param component  the component to add
   */
  public void addComponent(
    ComponentBean component)
  {
    // Generic "includes" will not have a component type
    if (component.getComponentType() != null)
    {
      component.attach(this);
      _components.put(component.getComponentType(), component);
    }
  }

  /**
   * Returns the component for this component type.
   *
   * @param componentType  the component type to find
   */
  public ComponentBean findComponent(
    String componentType)
  {
    return _components.get(componentType);
  }

  /**
   * Returns true if this faces config has any components.
   *
   * @return true  if this faces config has any components,
   *         otherwise false
   */
  public boolean hasComponents()
  {
    return !_components.isEmpty();
  }

  /**
   * Returns an iterator for all components in this faces
   * config.
   *
   * @return  the component iterator
   */
  public Iterator<ComponentBean> components()
  {
    return _components.values().iterator();
  }

  /**
   * Adds an event to this faces config document.
   *
   * @param event  the event to add
   */
  public void addEvent(
    EventBean event)
  {
    if (event.getEventType() == null)
    {
      _warning("Missing event type");
    }
    else if (event.getEventListenerClass() == null)
    {
      _warning("Event \"" + event.getEventType() + "\" " +
                   "has no listener class");
    }
    else if (event.getEventClass() == null)
    {
      _warning("Event \"" + event.getEventType() + "\" " +
                   "has no event class");
    }
    else
    {
      event.attach(this);
      _events.put(event.getEventType(), event);
    }
  }

  private void _warning(String s)
  {
    _LOG.warning(s+"\n  parsing resource:"+getCurrentResource());
  }

  /**
   * Returns the event for this event type.
   *
   * @param eventType  the event type to find
   */
  public EventBean findEvent(
    String eventType)
  {
    return _events.get(eventType);
  }

  /**
   * Returns true if this faces config has any events.
   *
   * @return true  if this faces config has any events,
   *         otherwise false
   */
  public boolean hasEvents()
  {
    return !_events.isEmpty();
  }

  /**
   * Returns an iterator for all events in this faces
   * config.
   *
   * @return  the event iterator
   */
  public Iterator<EventBean> events()
  {
    return _events.values().iterator();
  }

  /**
   * Adds a render kit to this faces config document.
   *
   * @param renderKit  the render kit to add
   */
  public void addRenderKit(
    RenderKitBean renderKit)
  {
    String renderKitId = renderKit.getRenderKitId();
    RenderKitBean existing = findRenderKit(renderKitId);

    if (existing == null)
    {
      renderKit.attach(this);
      _renderKits.put(renderKitId, renderKit);
    }
    else
    {
      existing.addAllRenderers(renderKit);
    }
  }

  /**
   * Returns the render kit for this render kit id.
   *
   * @param renderKitId  the render kit id to find
   */
  public RenderKitBean findRenderKit(
    String renderKitId)
  {
    return _renderKits.get(renderKitId);
  }

  /**
   * Returns true if this faces config has any render kits.
   *
   * @return true  if this faces config has any render kits,
   *         otherwise false
   */
  public boolean hasRenderKits()
  {
    return !_renderKits.isEmpty();
  }

  /**
   * Returns an iterator for all render kits in this faces
   * config.
   *
   * @return  the render kit iterator
   */
  public Iterator renderKits()
  {
    return _renderKits.values().iterator();
  }

  public URL getCurrentResource()
  {
    return _currentResource;
  }

  public URL setCurrentResource(URL resource)
  {
    URL _cur = _currentResource;
    _currentResource = resource;
    return _cur;
  }

  /**
   * Performs any processing of the meta-data that must be performed after all of the
   * meta-data has been collected. This includes processing on super-class data and other
   * inter-related computations that cannot be done as the data is being parsed.
   */
  public void performPostProcessing()
  {
    _identifyOverriddenProperies();
  }

  private void _identifyOverriddenProperies()
  {
    for (ComponentBean component : _components.values())
    {
      ComponentBean parentComponent = component.resolveSupertype();
      if (parentComponent == null)
      {
        continue;
      }

      for (Iterator<PropertyBean> iter = component.properties(); iter.hasNext();)
      {
        PropertyBean property = iter.next();
        PropertyBean parentProperty = parentComponent.findProperty(property.getPropertyName(),
                                        true);
        if (parentProperty != null)
        {
          property.setOverride(true);
        }
      }
    }
  }

  private Map<String, ConverterBean> _converters = new TreeMap<String, ConverterBean>();
  private Map<String, ValidatorBean> _validators = new TreeMap<String, ValidatorBean>();
  private Map<String, ComponentBean> _components = new TreeMap<String, ComponentBean>();
  private Map<String, EventBean> _events = new TreeMap<String, EventBean>();
  private Map<String, RenderKitBean> _renderKits = new TreeMap<String, RenderKitBean>();
  private URL _currentResource = null;

  static private final Logger _LOG = Logger.getLogger(FacesConfigBean.class.getName());
}
