content: /*
   * Copyright (c) 2008. All rights reserved.
   */
  package ro.isdc.wro.model;
  
  import static org.apache.commons.lang3.Validate.notNull;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  import org.apache.commons.lang3.Validate;
  import org.apache.commons.lang3.builder.EqualsBuilder;
  import org.apache.commons.lang3.builder.HashCodeBuilder;
  import org.apache.commons.lang3.builder.ToStringBuilder;
  import org.apache.commons.lang3.builder.ToStringStyle;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import ro.isdc.wro.WroRuntimeException;
  import ro.isdc.wro.model.group.Group;
  import ro.isdc.wro.model.group.InvalidGroupNameException;
  import ro.isdc.wro.model.resource.Resource;
  
  /**
   * The resource model encapsulates the information about all existing groups.
   *
   * @author Alex Objelean
   * @created Created on Oct 30, 2008
   */
  public final class WroModel {
    private static final Logger LOG = LoggerFactory.getLogger(WroModel.class);
    /**
     * Set of groups.
     */
    private Set<Group> groups = new HashSet<Group>();
  
    /**
     * @return a readonly collection of groups.
     */
    public final Collection<Group> getGroups() {
      return Collections.unmodifiableSet(groups);
    }
  
    /**
     * @param groups
     *          the groups to set
     */
    public final WroModel setGroups(final Collection<Group> groups) {
      notNull(groups, "groups cannot be null!");
      LOG.debug("setGroups: {}", groups);
      identifyDuplicateGroupNames(groups);
      this.groups = new HashSet<Group>(groups);
      return this;
    }
  
    /**
     * @param resource
     *          the {@link Resource} to search in all available groups.
     * @return t collection of group names containing provided resource. If the resource is not availalbe, an empty
     *         collection will be returned.
     * @deprecated use {@link WroModelInspector#getGroupNamesContainingResource(String)}
     */
    @Deprecated
    public Collection<String> getGroupNamesContainingResource(final String resourceUri) {
      return new WroModelInspector(this).getGroupNamesContainingResource(resourceUri);
    }
  
    /**
     * Identify duplicate group names.
     *
     * @param groups a collection of group to validate.
     */
    private void identifyDuplicateGroupNames(final Collection<Group> groups) {
      LOG.debug("identifyDuplicateGroupNames");
      final List<String> groupNames = new ArrayList<String>();
      for (final Group group : groups) {
        if (groupNames.contains(group.getName())) {
          throw new WroRuntimeException("Duplicate group name detected: " + group.getName());
        }
        groupNames.add(group.getName());
      }
    }
  
    /**
     * @param name
     *          of group to find.
     * @return group with searched name.
     * @throws runtime
     *           exception if group is not found.
     * @deprecated use {@link WroModelInspector#getGroupByName(String)}
     */
    @Deprecated
    public Group getGroupByName(final String name) {
      final WroModelInspector modelInspector = new WroModelInspector(this);
      final Group group = modelInspector.getGroupByName(name);
      if (group == null) {
        throw new InvalidGroupNameException(String.format("There is no such group: '%s'. Available groups are: [%s]", name,
            modelInspector.getGroupNamesAsString()));
      }
      return group;
    }
  
  /**
     * Merge this model with another model. This is useful for supporting model imports.
     *
     * @param importedModel model to import.
     */
    public void merge(final WroModel importedModel) {
      Validate.notNull(importedModel, "imported model cannot be null!");
      LOG.debug("merging importedModel: {}", importedModel);
      for (final String groupName : new WroModelInspector(importedModel).getGroupNames()) {
        if (new WroModelInspector(this).getGroupNames().contains(groupName)) {
          throw new WroRuntimeException("Duplicate group name detected: " + groupName);
        }
        final Group importedGroup = new WroModelInspector(importedModel).getGroupByName(groupName);
        addGroup(importedGroup);
      }
    }
  
    /**
     * Add a single group to the model.
     * @param group a not null {@link Group}.
     */
    public WroModel addGroup(final Group group) {
      Validate.notNull(group);
      groups.add(group);
      return this;
    }
  
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(final Object obj) {
      return EqualsBuilder.reflectionEquals(this, obj, true);
    }
  
    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
      return HashCodeBuilder.reflectionHashCode(this);
    }
  
    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
      return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append(
          "groups", this.groups).toString();
    }
  }
  