View Javadoc

    1   /* MapType
    2    *
    3    * $Id: MapType.java 4661 2006-09-25 23:11:16Z paul_jack $
    4    *
    5    * Created on Jan 8, 2004
    6    *
    7    * Copyright (C) 2004 Internet Archive.
    8    *
    9    * This file is part of the Heritrix web crawler (crawler.archive.org).
    10   *
    11   * Heritrix is free software; you can redistribute it and/or modify
    12   * it under the terms of the GNU Lesser Public License as published by
    13   * the Free Software Foundation; either version 2.1 of the License, or
    14   * any later version.
    15   *
    16   * Heritrix is distributed in the hope that it will be useful,
    17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19   * GNU Lesser Public License for more details.
    20   *
    21   * You should have received a copy of the GNU Lesser Public License
    22   * along with Heritrix; if not, write to the Free Software
    23   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24   */
    25  package org.archive.crawler.settings;
    26
    27  import java.util.Iterator;
    28  import java.util.List;
    29
    30  import javax.management.AttributeNotFoundException;
    31  import javax.management.InvalidAttributeValueException;
    32
    33  import org.archive.crawler.settings.Constraint.FailedCheck;
    34
    35  /*** This class represents a container of settings.
    36   *
    37   * This class is usually used to make it possible to have a dynamic number
    38   * of ModuleTypes like for instance a list of filters of different type.
    39   *
    40   * When this type is overridden on a per domain basis, the following
    41   * restrictions apply:
    42   * <ul>
    43   *   <li>Added elements is placed after the elements in the map it overrides.
    44   *   <li>You can not remove elements from the map it overrides. If it is
    45   *       necessary to be able to remove an element, this has to be done by
    46   *       adding some disable feature to the modules referenced by the map. An
    47   *       example of this is the enabled attribute on the
    48   *       {@link org.archive.crawler.framework.Filter} class.
    49   *   <li>All elements defined in maps that this map overrides might have their
    50   *       settings changed, but the order can not be changed.
    51   * </ul>
    52   *
    53   * @author John Erik Halse
    54   */
    55  public class MapType extends ComplexType {
    56
    57      private static final long serialVersionUID = -3694800285930202700L;
    58
    59      /*** The content type allowed for this map. */
    60      private final Type definition;
    61
    62      /*** Construct a new MapType object.
    63       *
    64       * @param name the name of this element.
    65       * @param description the description of the attribute.
    66       */
    67      public MapType(String name, String description) {
    68          this(name, description, Object.class);
    69      }
    70
    71      /*** Construct a new MapType object.
    72       *
    73       * @param name the name of this element.
    74       * @param description the description of the attribute.
    75       * @param type the type allowed for this map
    76       */
    77      public MapType(String name, String description, Class type) {
    78          super(name, description);
    79          this.definition = new SimpleType("dummy", "dummy", null);
    80          this.definition.setLegalValueType(type);
    81      }
    82
    83      /*** Add a new element to this map.
    84       *
    85       * @param settings the settings object for this method to have effect.
    86       * @param element the element to be added.
    87       * @return Element added.
    88       * @throws InvalidAttributeValueException
    89       */
    90      public Type addElement(CrawlerSettings settings, Type element)
    91          throws InvalidAttributeValueException {
    92          settings = settings == null ? globalSettings() : settings;
    93
    94          if (settings != globalSettings()) {
    95              try {
    96                  getAttribute(settings, element.getName());
    97                  // Element exist, throw an exception
    98                  throw new IllegalArgumentException(
    99                      "Duplicate element: " + element.getName());
    100
    101             } catch (AttributeNotFoundException e) {
    102                 // Element doesn't exist, ok to add
    103             }
    104         }
    105
    106         if (!(element instanceof MapType)) {
    107             return super.addElement(settings, element);
    108         } else {
    109             throw new IllegalArgumentException("Nested maps are not allowed.");
    110         }
    111     }
    112
    113     /*** Remove an attribute from the map.
    114      *
    115      * @param settings the settings object for which this method has effect.
    116      * @param name name of the attribute to remove.
    117      * @return the element that was removed.
    118      * @throws AttributeNotFoundException is thrown if there is no attribute
    119      *         with the submitted name.
    120      */
    121     public Object removeElement(CrawlerSettings settings, String name)
    122       throws AttributeNotFoundException {
    123         settings = settings == null ? globalSettings() : settings;
    124         return settings.getData(this).removeElement(name);
    125     }
    126
    127     /*** Move an attribute up one place in the list.
    128      *
    129      * @param settings the settings object for which this method has effect.
    130      * @param name name of attribute to move.
    131      * @return true if attribute was moved, false if attribute was already
    132      *              at the top.
    133      * @throws AttributeNotFoundException is thrown if there is no attribute
    134      *         with the submitted name.
    135      */
    136     public boolean moveElementUp(CrawlerSettings settings, String name)
    137       throws AttributeNotFoundException {
    138         settings = settings == null ? globalSettings() : settings;
    139         return settings.getData(this).moveElementUp(name);
    140     }
    141
    142     /*** Move an attribute down one place in the list.
    143      *
    144      * @param settings the settings object for which this method has effect.
    145      * @param name name of attribute to move.
    146      * @return true if attribute was moved, false if attribute was already
    147      *              at bottom.
    148      * @throws AttributeNotFoundException is thrown if there is no attribute
    149      *         with the submitted name.
    150      */
    151     public boolean moveElementDown(CrawlerSettings settings, String name)
    152       throws AttributeNotFoundException {
    153         settings = settings == null ? globalSettings() : settings;
    154         return settings.getData(this).moveElementDown(name);
    155     }
    156
    157     /*** Returns true if this map is empty.
    158      *
    159      * @param context the settings object for which this set of elements
    160      * are valid.
    161      * @return true if this map is empty.
    162      */
    163     public boolean isEmpty(Object context) {
    164         Context ctxt = getSettingsFromObject(context);
    165
    166         DataContainer data = getDataContainerRecursive(ctxt);
    167         while (data != null) {
    168             if (data.hasAttributes()) {
    169                 return false;
    170             }
    171             ctxt.settings = data.getSettings().getParent();
    172             data = getDataContainerRecursive(ctxt);
    173         }
    174         return true;
    175     }
    176
    177     /*** Get the number of elements in this map.
    178      *
    179      * @param context the settings object for which this set of elements
    180      *                 are valid.
    181      * @return the number of elements in this map.
    182      */
    183     public int size(Object context) {
    184         Context ctxt = getSettingsFromObject(context);
    185
    186         int size = 0;
    187         DataContainer data = getDataContainerRecursive(ctxt);
    188         while (data != null) {
    189             size += data.size();
    190             ctxt.settings = data.getSettings().getParent();
    191             data = getDataContainerRecursive(ctxt);
    192         }
    193         return size;
    194     }
    195
    196     /***
    197      * Get the content type definition for attributes of this map.
    198      *
    199      * @param attributeName since all attributes of a map are of the same type,
    200      * this value is not used.
    201      * @return the content type definition for attributes of this map.
    202      */
    203     Type getDefinition(String attributeName) {
    204         return definition;
    205     }
    206
    207     /***
    208      * Get the content type allowed for this map.
    209      *
    210      * @return the content type allowed for this map.
    211      */
    212     public Class getContentType() {
    213         return this.definition.getLegalValueType();
    214     }
    215
    216     FailedCheck checkValue(CrawlerSettings settings, String attributeName,
    217             Type definition, Object value) {
    218         FailedCheck res = super.checkValue(settings, attributeName, definition,
    219                 value);
    220
    221         definition = super.getDefinition(attributeName);
    222
    223         // Check if value fulfills any constraints
    224         List constraints = definition != null ? definition.getConstraints()
    225                 : null;
    226         if (constraints != null) {
    227             FailedCheck ac = null;
    228             for (Iterator it = constraints.iterator(); it.hasNext()
    229                     && ac == null;) {
    230                 ac = ((Constraint) it.next()).check(settings, this, definition,
    231                         value);
    232                 if (res == null
    233                         || ac.getLevel().intValue() >= res.getLevel()
    234                                 .intValue()) {
    235                     res = ac;
    236                 }
    237             }
    238         }
    239
    240         return res;
    241     }
    242
    243     /* (non-Javadoc)
    244      * @see org.archive.crawler.settings.Type#addConstraint(org.archive.crawler.settings.Constraint)
    245      */
    246     public void addConstraint(Constraint constraint) {
    247         definition.addConstraint(constraint);
    248     }
    249
    250     /* (non-Javadoc)
    251      * @see org.archive.crawler.settings.Type#getConstraints()
    252      */
    253     public List getConstraints() {
    254         return definition.getConstraints();
    255     }
    256 }