/**
   * Calculates the date to use for comparison of this resource based on the given date identifiers.
   *
   * <p>
   *
   * @param cms the current OpenCms user context
   * @param resource the resource to create the key for
   * @param dateIdentifiers the date identifiers to use for selecting the date
   * @param defaultValue the default value to use in case no value can be calculated
   * @return the calculated date
   * @see CmsDateResourceComparator for a description about how the date identifieres are used
   */
  public static long calculateDate(
      CmsObject cms, CmsResource resource, List<String> dateIdentifiers, long defaultValue) {

    long result = 0;
    List<CmsProperty> properties = null;
    for (int i = 0, size = dateIdentifiers.size(); i < size; i++) {
      // check all configured comparisons
      String date = dateIdentifiers.get(i);
      int pos = DATE_ATTRIBUTES_LIST.indexOf(date);
      switch (pos) {
        case 0: // "dateCreated"
          result = resource.getDateCreated();
          break;
        case 1: // "dateLastModified"
          result = resource.getDateLastModified();
          break;
        case 2: // "dateContent"
          if (resource.isFile()) {
            // date content makes no sense for folders
            result = resource.getDateContent();
          }
          break;
        case 3: // "dateReleased"
          long dr = resource.getDateReleased();
          if (dr != CmsResource.DATE_RELEASED_DEFAULT) {
            // default release date must be ignored
            result = dr;
          }
          break;
        case 4: // "dateExpired"
          long de = resource.getDateExpired();
          if (de != CmsResource.DATE_EXPIRED_DEFAULT) {
            // default expiration date must be ignored
            result = de;
          }
          break;
        default:
          // of this is not an attribute, assume this is a property
          if (properties == null) {
            // we may not have to read the properties since the user may only use attributes,
            // so use lazy initializing here
            try {
              properties = cms.readPropertyObjects(resource, false);
            } catch (CmsException e) {
              // use empty list in case of an error, to avoid further re-read tries
              properties = Collections.emptyList();
            }
          }
          String propValue = CmsProperty.get(date, properties).getValue();
          if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(propValue)) {
            try {
              result = Long.parseLong(propValue.trim());
            } catch (NumberFormatException e) {
              // maybe we have better luck with the next property
            }
          }
          break;
      }
      if (result != 0) {
        // if a date value has been found, terminate the loop
        break;
      }
    }
    if (result == 0) {
      // if nothing else was found, use default
      result = defaultValue;
    }
    return result;
  }
  /**
   * Writes a property value for a resource, if the value was changed.
   *
   * <p>
   *
   * @param res the resource to write the property to
   * @param propName the name of the property definition
   * @param propValue the new value of the property
   * @param currentProperty the old property object
   * @throws CmsException if something goes wrong
   */
  protected void writeProperty(
      CmsResource res, String propName, String propValue, CmsProperty currentProperty)
      throws CmsException {

    // check if current property is not the null property
    if (currentProperty.isNullProperty()) {
      // create new property object
      currentProperty = new CmsProperty();
      currentProperty.setName(propName);
    }

    if (CmsStringUtil.isEmptyOrWhitespaceOnly(propValue)) {
      // parameter is empty, determine the value to delete
      boolean writeProperty = false;
      if (currentProperty.getStructureValue() != null) {
        currentProperty.setStructureValue(CmsProperty.DELETE_VALUE);
        currentProperty.setResourceValue(null);
        writeProperty = true;
      } else if (currentProperty.getResourceValue() != null) {
        currentProperty.setResourceValue(CmsProperty.DELETE_VALUE);
        currentProperty.setStructureValue(null);
        writeProperty = true;
      }
      if (writeProperty) {
        // write the updated property object
        getCms().writePropertyObject(getCms().getSitePath(res), currentProperty);
      }
    } else {
      // parameter is not empty, check if the value has changed
      if (!propValue.equals(currentProperty.getValue())) {
        if ((currentProperty.getStructureValue() == null)
            && (currentProperty.getResourceValue() == null)) {
          // new property, determine setting from OpenCms workplace configuration
          if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) {
            currentProperty.setStructureValue(propValue);
            currentProperty.setResourceValue(null);
          } else {
            currentProperty.setResourceValue(propValue);
            currentProperty.setStructureValue(null);
          }
        } else if (currentProperty.getStructureValue() != null) {
          // structure value has to be updated
          currentProperty.setStructureValue(propValue);
          currentProperty.setResourceValue(null);
        } else {
          // resource value has to be updated
          currentProperty.setResourceValue(propValue);
          currentProperty.setStructureValue(null);
        }
        // write the updated property object
        getCms().writePropertyObject(getCms().getSitePath(res), currentProperty);
      }
    }
  }
  /**
   * Fills a single item.
   *
   * <p>
   *
   * @param resource the corresponding resource.
   * @param item the item to fill.
   * @param id used for the ID column.
   */
  @SuppressWarnings("unchecked")
  private void fillItem(final CmsResource resource, final CmsListItem item, final int id) {

    CmsObject cms = this.getCms();
    CmsXmlContent xmlContent;

    I_CmsResourceType type;
    String iconPath;

    // fill path column:
    String sitePath = cms.getSitePath(resource);
    item.set(LIST_COLUMN_PATH, sitePath);

    // fill language node existence column:
    item.set(LIST_COLUMN_PATH, sitePath);
    boolean languageNodeExists = false;
    String languageNodeHtml;

    List<Locale> sysLocales = OpenCms.getLocaleManager().getAvailableLocales();
    try {
      xmlContent = CmsXmlContentFactory.unmarshal(cms, cms.readFile(resource));
      for (Locale locale : sysLocales) {
        languageNodeExists = xmlContent.hasLocale(locale);
        if (languageNodeExists) {
          languageNodeHtml = "<input type=\"checkbox\" checked=\"checked\" disabled=\"disabled\"/>";
        } else {
          languageNodeHtml = "<input type=\"checkbox\" disabled=\"disabled\"/>";
        }
        item.set(locale.toString(), languageNodeHtml);
      }
    } catch (Throwable e1) {
      LOG.error(
          Messages.get().getBundle().key(Messages.LOG_ERR_LANGUAGECOPY_DETERMINE_LANGUAGE_NODE_1),
          e1);
      languageNodeHtml = "n/a";
      for (Locale locale : sysLocales) {
        item.set(locale.toString(), languageNodeHtml);
      }
    }

    // type column:
    type = OpenCms.getResourceManager().getResourceType(resource);
    item.set(LIST_COLUMN_RESOURCETYPE, type.getTypeName());

    // icon column with title property for tooltip:
    String title = "";
    try {
      CmsProperty titleProperty =
          cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, true);
      title = titleProperty.getValue();
    } catch (CmsException e) {
      LOG.warn(Messages.get().getBundle().key(Messages.LOG_WARN_LANGUAGECOPY_READPROP_1), e);
    }

    iconPath =
        getSkinUri()
            + CmsWorkplace.RES_PATH_FILETYPES
            + OpenCms.getWorkplaceManager().getExplorerTypeSetting(type.getTypeName()).getIcon();
    String iconImage;
    iconImage =
        "<img src=\""
            + iconPath
            + "\" alt=\""
            + type.getTypeName()
            + "\" title=\""
            + title
            + "\" />";
    item.set(LIST_COLUMN_ICON, iconImage);
  }