Package pt.webdetails.cdf.dd.model.meta

Source Code of pt.webdetails.cdf.dd.model.meta.MetaModel$Builder

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

package pt.webdetails.cdf.dd.model.meta;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import pt.webdetails.cdf.dd.model.core.KnownThingKind;
import pt.webdetails.cdf.dd.model.meta.validation.DuplicatePropertyTypeError;
import pt.webdetails.cdf.dd.model.core.validation.ValidationException;

/**
* @author dcleao
*/
public class MetaModel extends MetaObject
{
  private static final Log _logger = LogFactory.getLog(MetaModel.class);
 
  // NOTE: The fact that there are some legacy components
  // whose name differs only by case...causes us to need to recognize the difference.
  // (See: base/components/datasources/XactionResultSetRender.xml and
  //  base/components/others/XActionRender.xml)
  private final Map<String, ComponentType> _componentTypesByName;
  private final Map<String, ComponentType> _componentTypesByLegacyName;
 
  private final Map<String, PropertyType>  _propertyTypesByLowerName;

  protected MetaModel(Builder builder) throws ValidationException
  {
    super(builder);

    this._componentTypesByName = new LinkedHashMap<String, ComponentType>();
   
    // Don't need two «keep order» implementations.
    this._componentTypesByLegacyName = new HashMap<String, ComponentType>();
   
    this._propertyTypesByLowerName  = new LinkedHashMap<String, PropertyType>();
   
    for(PropertyType.Builder propBuilder : builder._propertyTypes)
    {
      PropertyType prop;
      try
      {
        prop = propBuilder.build();
      }
      catch(ValidationException ex)
      {
        // Ignore PropertyType, log warning and continue.
        _logger.warn(ex.getError());
        continue;
      }
     
      String key = prop.getName().toLowerCase();
      if(!this._propertyTypesByLowerName.containsKey(key))
      {
        this._propertyTypesByLowerName.put(key, prop);
      }
      else
      {
        // Ignore PropertyType, log warning and continue.
        _logger.warn(new DuplicatePropertyTypeError(prop));
        continue;
      }
    }

    // Create a PropertyType source to support building of ComponentType.s
   
    // A sub-type of IObectBuildContext
    IPropertyTypeSource propSource = this.getPropertyTypeSource();
   
    for(ComponentType.Builder compBuilder : builder._componentTypes)
    {
      ComponentType comp;
      try
      {
        comp = compBuilder.build(propSource);
      }
      catch(ValidationException ex)
      {
        // Ignore ComponentType, log warning and continue.
        _logger.warn(ex.getError());
        continue;
      }
     
      String key = comp.getName();
     
      // Detect Component Type Override.
      ComponentType oldComp = this._componentTypesByName.get(key);
     
      // Add new component
      this._componentTypesByName.put(key, comp);
      for(String legacyName : comp.getLegacyNames())
      {
        this._componentTypesByLegacyName.put(legacyName, comp);
      }
     
      // Check if oldComp was registered under additional legacy names.
      // If a component is overriden more than once, we accumulate all legacyNames "so far".
      // This thus overrides all mappings to the previous definition.
      if(oldComp != null)
      {
        _logger.info("ComponentType '" + oldComp.getLabel() + "' was overriden.");
       
        List<String> alternateNames = null;
        for(Map.Entry<String, ComponentType> entry : this._componentTypesByLegacyName.entrySet())
        {
          if(entry.getValue() == oldComp)
          {
            if(alternateNames == null) { alternateNames = new ArrayList<String>(); }
            alternateNames.add(entry.getKey());
          }
        }
       
        if(alternateNames != null)
        {
          for(String altName : alternateNames)
          {
            // Replace oldComp by comp
            this._componentTypesByLegacyName.put(altName, comp);
          }
        }
      }
    }
  }

  public final IPropertyTypeSource getPropertyTypeSource()
  {
    final MetaModel me = this;
    return new IPropertyTypeSource() {
      public PropertyType getProperty(String name)
      {
        String lkey = name != null ? name.toLowerCase() : "";
        return me._propertyTypesByLowerName.get(lkey);
      }
    };
  }

  @Override
  public String getKind()
  {
    return KnownThingKind.MetaModel;
  }
 
  public ComponentType getComponentType(String name)
  {
    ComponentType comp = this.tryGetComponentType(name);
    if(comp == null)
    {
      throw new IllegalArgumentException("There is no component type with name '" + name + "'.");
    }

    return comp;
  }

  public ComponentType tryGetComponentType(String name)
  {
    if(StringUtils.isEmpty(name)) { throw new IllegalArgumentException("name"); }

    ComponentType compType = this._componentTypesByName.get(name);
    return compType != null ? compType : this._componentTypesByLegacyName.get(name);
  }

  public PropertyType getPropertyType(String name)
  {
    PropertyType prop = this.tryGetPropertyType(name);
    if(prop == null)
    {
      throw new IllegalArgumentException("There is no property type with name '" + name + "'.");
    }

    return prop;
  }

  public PropertyType tryGetPropertyType(String name)
  {
    if(StringUtils.isEmpty(name)) { throw new IllegalArgumentException("name"); }

    return this._propertyTypesByLowerName.get(name.toLowerCase());
  }

  public Iterable<ComponentType> getComponentTypes()
  {
    return this._componentTypesByName.values();
  }

  public int getComponentTypeCount()
  {
    return this._componentTypesByName.size();
  }

  public Iterable<PropertyType>  getPropertyTypes()
  {
    return this._propertyTypesByLowerName.values();
  }

  public int getPropertyTypeCount()
  {
    return this._propertyTypesByLowerName.size();
  }

  public static class Builder extends MetaObject.Builder
  {
    private final List<ComponentType.Builder> _componentTypes;
    private final List<PropertyType.Builder>  _propertyTypes;

    public Builder()
    {
      super();
     
      this._componentTypes = new ArrayList<ComponentType.Builder>();
      this._propertyTypes  = new ArrayList<PropertyType.Builder>();
    }

    public Builder addComponent(ComponentType.Builder comp)
    {
      if(comp == null) { throw new IllegalArgumentException("comp"); }

      this._componentTypes.add(comp);
      return this;
    }

    public Builder addProperty(PropertyType.Builder prop)
    {
      if(prop == null) { throw new IllegalArgumentException("prop"); }

      this._propertyTypes.add(prop);
      return this;
    }

    public MetaModel build() throws ValidationException
    {
      return new MetaModel(this);
    }
  }
}
TOP

Related Classes of pt.webdetails.cdf.dd.model.meta.MetaModel$Builder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.