Package org.pentaho.reporting.tools.configeditor.model

Source Code of org.pentaho.reporting.tools.configeditor.model.ConfigDescriptionModel$ConfigEntryComparator

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors.  All rights reserved.
*/

package org.pentaho.reporting.tools.configeditor.model;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import javax.swing.AbstractListModel;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.xmlns.common.AttributeList;
import org.pentaho.reporting.libraries.xmlns.parser.ParseException;
import org.pentaho.reporting.libraries.xmlns.writer.CharacterEntityParser;
import org.pentaho.reporting.libraries.xmlns.writer.DefaultTagDescription;
import org.pentaho.reporting.libraries.xmlns.writer.XmlWriter;
import org.pentaho.reporting.libraries.xmlns.writer.XmlWriterSupport;
import org.pentaho.reporting.tools.configeditor.ConfigEditorBoot;
import org.pentaho.reporting.tools.configeditor.Messages;
import org.pentaho.reporting.tools.configeditor.util.DOMUtilities;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
* This list model implementation collects all config description entries defined in JFreeReport. This model is used to
* create a configuration key definition; it directly manipulates the metadata for the keys as stored in the
* config-description.xml file.
*
* @author Thomas Morgner
*/
public class ConfigDescriptionModel extends AbstractListModel
{
  private static final Log logger = LogFactory.getLog(ConfigDescriptionModel.class);

  /**
   * Compares an config description entry against an other entry. This simple implementation just compares the names of
   * the two entries.
   */
  private static class ConfigEntryComparator implements Comparator, Serializable
  {
    /**
     * DefaultConstructor.
     */
    protected ConfigEntryComparator()
    {
    }

    /**
     * Compares its two arguments for order.  Returns a negative integer, zero, or a positive integer as the first
     * argument is less than, equal to, or greater than the second.<p>
     *
     * @param o1 the first object to compare
     * @param o2 the second object to compare
     * @return an integer indicating the comparison result.
     */
    public int compare(final Object o1, final Object o2)
    {
      if (o1 == null && o2 == null)
      {
        return 0;
      }
      if (o1 == null)
      {
        return -1;
      }
      if (o2 == null)
      {
        return 1;
      }
      final ConfigDescriptionEntry e1 = (ConfigDescriptionEntry) o1;
      final ConfigDescriptionEntry e2 = (ConfigDescriptionEntry) o2;
      return e1.getKeyName().compareTo(e2.getKeyName());
    }
  }

  /**
   * The content of this list; all config description entries.
   */
  private final ArrayList content;

  /**
   * Provides access to externalized strings
   */
  private Messages messages;

  /**
   * Creates a new, initially empty ConfigDescriptionModel.
   */
  public ConfigDescriptionModel()
  {
    messages = Messages.getInstance();
    content = new ArrayList();
  }

  /**
   * Adds the given entry to the end of the list.
   *
   * @param entry the new entry.
   */
  public void add(final ConfigDescriptionEntry entry)
  {
    if (entry == null)
    {
      throw new NullPointerException(messages.getString(
          "ConfigDescriptionModel.ERROR_0001_ENTRY_IS_NULL")); //$NON-NLS-1$
    }
    // Only add unique elements ...
    final int index = findEntry(entry.getKeyName());
    if (index == -1)
    {
      content.add(entry);
      updated();
    }
    else
    {
      content.set(index, entry);
    }
  }

  private int findEntry(final String key)
  {
    for (int i = 0; i < content.size(); i++)
    {
      final ConfigDescriptionEntry configDescriptionEntry = (ConfigDescriptionEntry) content.get(i);
      if (key.equals(configDescriptionEntry.getKeyName()))
      {
        return i;
      }
    }
    return -1;
  }

  /**
   * Removes the given entry from the list.
   *
   * @param entry the entry that should be removed.
   */
  public void remove(final ConfigDescriptionEntry entry)
  {
    if (entry == null)
    {
      throw new NullPointerException(messages.getString(
          "ConfigDescriptionModel.ERROR_0002_ENTRY_IS_NULL")); //$NON-NLS-1$
    }

    final int index = findEntry(entry.getKeyName());
    if (index != -1)
    {
      content.remove(index);
      updated();
    }
  }

  public void removeAll(final int[] indices)
  {
    if (indices.length == 0)
    {
      return;
    }

    final Object[] entries = new Object[indices.length];
    for (int i = indices.length - 1; i >= 0; i--)
    {
      entries[i] = content.get(indices[i]);
    }
    for (int i = 0; i < entries.length; i++)
    {
      content.remove(entries[i]);
    }
    updated();
  }

  /**
   * Returns the entry stored on the given list position.
   *
   * @param pos the position
   * @return the entry
   * @throws IndexOutOfBoundsException if the position is invalid.
   */
  public ConfigDescriptionEntry get(final int pos)
  {
    return (ConfigDescriptionEntry) content.get(pos);
  }

  /**
   * Fires an contents changed event for all elements in the list.
   */
  public void updated()
  {
    fireContentsChanged(this, 0, getSize());
  }

  /**
   * Returns the index of the given entry or -1, if the entry is not in the list.
   *
   * @param entry the entry whose position should be searched.
   * @return the position of the entry
   */
  public int indexOf(final ConfigDescriptionEntry entry)
  {
    if (entry == null)
    {
      throw new NullPointerException(messages.getString(
          "ConfigDescriptionModel.ERROR_0003_ENTRY_IS_NULL")); //$NON-NLS-1$
    }
    return findEntry(entry.getKeyName());
  }

  /**
   * Checks whether the given entry is already contained in this list.
   *
   * @param entry the entry that should be checked.
   * @return true, if the entry is already added, false otherwise.
   */
  public boolean contains(final ConfigDescriptionEntry entry)
  {
    if (entry == null)
    {
      throw new NullPointerException(messages.getString(
          "ConfigDescriptionModel.ERROR_0004_ENTRY_IS_NULL")); //$NON-NLS-1$
    }
    return findEntry(entry.getKeyName()) > -1;
  }

  /**
   * Sorts the entries of the list. Be aware that calling this method does not fire an updat event; you have to do this
   * manually.
   */
  public void sort()
  {
    Collections.sort(content, new ConfigEntryComparator());
    updated();
  }

  /**
   * Returns the contents of this model as object array.
   *
   * @return the contents of the model as array.
   */
  public ConfigDescriptionEntry[] toArray()
  {
    return (ConfigDescriptionEntry[]) content.toArray(new ConfigDescriptionEntry[content.size()]);
  }

  /**
   * Returns the length of the list.
   *
   * @return the length of the list
   */
  public int getSize()
  {
    return content.size();
  }

  /**
   * Returns the value at the specified index.
   *
   * @param index the requested index
   * @return the value at <code>index</code>
   */
  public Object getElementAt(final int index)
  {
    final ConfigDescriptionEntry entry = get(index);
    if (entry == null)
    {
      return null;
    }
    return entry.getKeyName();
  }

  /**
   * Imports all entries from the given report configuration. Only new entries will be added to the list. This does not
   * add report properties supplied via the System.properties.
   *
   * @param config the report configuration from where to add the entries.
   */
  public void importFromConfig(final Configuration config)
  {
    final Iterator it = config.findPropertyKeys(""); //$NON-NLS-1$
    while (it.hasNext())
    {
      final String keyname = (String) it.next();
      if (System.getProperties().containsKey(keyname))
      {
        continue;
      }

      final TextConfigDescriptionEntry entry = new TextConfigDescriptionEntry(keyname);
      if (contains(entry) == false)
      {
        add(entry);
      }
    }
  }

  /**
   * Loads the entries from the given xml file. The file must be in the format of the config-description.xml file.
   *
   * @param in the inputstream from where to read the file
   * @throws IOException                  if an error occured while reading the file
   * @throws SAXException                 if an XML parse error occurs.
   * @throws ParserConfigurationException if the XML parser could not be initialized.
   */
  public void load(final InputStream in)
      throws IOException, SAXException, ParserConfigurationException
  {
    content.clear();
    final Document doc = DOMUtilities.parseInputStream(in);
    final Element e = doc.getDocumentElement();
    final NodeList list = e.getElementsByTagName("key"); //$NON-NLS-1$
    for (int i = 0; i < list.getLength(); i++)
    {
      final Element keyElement = (Element) list.item(i);
      final String keyName = keyElement.getAttribute("name"); //$NON-NLS-1$
      final boolean keyGlobal = "true".equals(keyElement.getAttribute("global")); //$NON-NLS-1$
      final boolean keyHidden = "true".equals(keyElement.getAttribute("hidden")); //$NON-NLS-1$
      final String descr = getDescription(keyElement).trim();

      final NodeList enumNodes = keyElement.getElementsByTagName("enum"); //$NON-NLS-1$
      if (enumNodes.getLength() != 0)
      {
        final String[] alteratives = collectEnumEntries((Element) enumNodes.item(0));
        final EnumConfigDescriptionEntry en = new EnumConfigDescriptionEntry(keyName);
        en.setDescription(descr);
        en.setGlobal(keyGlobal);
        en.setHidden(keyHidden);
        en.setOptions(alteratives);
        add(en);
        continue;
      }

      final NodeList classNodes = keyElement.getElementsByTagName("class"); //$NON-NLS-1$
      if (classNodes.getLength() != 0)
      {
        final Element classElement = (Element) classNodes.item(0);
        final String className = classElement.getAttribute("instanceof"); //$NON-NLS-1$
        if (className == null)
        {
          throw new ParseException(messages.getString(
              "ConfigDescriptionModel.ERROR_0005_MISSING_INSTANCEOF")); //$NON-NLS-1$
        }
        try
        {
          final ClassLoader classLoader = ObjectUtilities.getClassLoader(getClass());
          final Class baseClass = Class.forName(className, false, classLoader);
          final ClassConfigDescriptionEntry ce = new ClassConfigDescriptionEntry(keyName);
          ce.setBaseClass(baseClass);
          ce.setDescription(descr);
          ce.setGlobal(keyGlobal);
          ce.setHidden(keyHidden);
          add(ce);
          continue;
        }
        catch (Exception ex)
        {
          final String message = messages.getString(
              "ConfigDescriptionModel.ERROR_0006_BASE_CLASS_LOAD_FAILED"); //$NON-NLS-1$
          ConfigDescriptionModel.logger.error(message, ex);
          continue;
        }
      }

      final NodeList textNodes = keyElement.getElementsByTagName("text"); //$NON-NLS-1$
      if (textNodes.getLength() != 0)
      {
        final TextConfigDescriptionEntry textEntry = new TextConfigDescriptionEntry(keyName);
        textEntry.setDescription(descr);
        textEntry.setGlobal(keyGlobal);
        textEntry.setHidden(keyHidden);
        add(textEntry);
      }
    }
  }

  /**
   * A parser helper method which collects all enumeration entries from the given element.
   *
   * @param element the element from where to read the enumeration entries.
   * @return the entries as string array.
   */
  private String[] collectEnumEntries(final Element element)
  {
    final NodeList nl = element.getElementsByTagName("text"); //$NON-NLS-1$
    final String[] retval = new String[nl.getLength()];
    for (int i = 0; i < nl.getLength(); i++)
    {
      retval[i] = DOMUtilities.getText((Element) nl.item(i)).trim();
    }
    return retval;
  }

  /**
   * A parser helper method that returns the CDATA description of the given element.
   *
   * @param e the element from where to read the description.
   * @return the description text.
   */
  private String getDescription(final Element e)
  {
    final NodeList descr = e.getElementsByTagName("description"); //$NON-NLS-1$
    if (descr.getLength() == 0)
    {
      return ""; //$NON-NLS-1$
    }
    return DOMUtilities.getText((Element) descr.item(0));
  }

  /**
   * Saves the model into an xml file.
   *
   * @param out      the target output stream.
   * @param encoding the encoding of the content.
   * @throws IOException if an error occurs.
   * @noinspection IOResourceOpenedButNotSafelyClosed
   */
  public void save(final OutputStream out, final String encoding)
      throws IOException
  {
    // This print-writer will be flushed, but not closed, as closing the underlying stream is not desired here.
    final PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, encoding));
    final AttributeList attList = new AttributeList();
    attList.addNamespaceDeclaration("", ConfigEditorBoot.NAMESPACE); //$NON-NLS-1$

    final DefaultTagDescription tagDescription = new DefaultTagDescription();
    tagDescription.configure
        (ConfigEditorBoot.getInstance().getGlobalConfig(), "org.pentaho.reporting.tools.configeditor.writer.");
    final XmlWriter dwriter = new XmlWriter(writer, tagDescription);


    dwriter.writeXmlDeclaration(encoding);
    dwriter.writeTag(ConfigEditorBoot.NAMESPACE,
        "config-description", attList, XmlWriterSupport.OPEN); //$NON-NLS-1$

    final CharacterEntityParser parser = CharacterEntityParser.createXMLEntityParser();
    for (int i = 0; i < getSize(); i++)
    {
      final ConfigDescriptionEntry entry = get(i);
      final AttributeList p = new AttributeList();
      p.setAttribute(ConfigEditorBoot.NAMESPACE, "name", entry.getKeyName()); //$NON-NLS-1$
      p.setAttribute(ConfigEditorBoot.NAMESPACE, "global", String.valueOf(entry.isGlobal())); //$NON-NLS-1$
      p.setAttribute(ConfigEditorBoot.NAMESPACE, "hidden", String.valueOf(entry.isHidden())); //$NON-NLS-1$
      dwriter.writeTag(ConfigEditorBoot.NAMESPACE, "key", p, XmlWriterSupport.OPEN); //$NON-NLS-1$
      if (entry.getDescription() != null)
      {
        dwriter.writeTag(ConfigEditorBoot.NAMESPACE, "description", XmlWriterSupport.OPEN); //$NON-NLS-1$
        writer.write(parser.encodeEntities(entry.getDescription()));
        dwriter.writeCloseTag();
      }
      if (entry instanceof ClassConfigDescriptionEntry)
      {
        final ClassConfigDescriptionEntry ce = (ClassConfigDescriptionEntry) entry;
        if (ce.getBaseClass() != null)
        {
          dwriter.writeTag(ConfigEditorBoot.NAMESPACE, "class", "instanceof", //$NON-NLS-1$ //$NON-NLS-2$
              ce.getBaseClass().getName(), XmlWriterSupport.CLOSE);
        }
        else
        {
          dwriter.writeTag(ConfigEditorBoot.NAMESPACE, "class", "instanceof", //$NON-NLS-1$ //$NON-NLS-2$
              "java.lang.Object", XmlWriterSupport.CLOSE); //$NON-NLS-1$
        }
      }
      else if (entry instanceof TextConfigDescriptionEntry)
      {
        dwriter.writeTag(ConfigEditorBoot.NAMESPACE, "text", //$NON-NLS-1$
            new AttributeList(), XmlWriterSupport.CLOSE);
      }
      else if (entry instanceof EnumConfigDescriptionEntry)
      {
        final EnumConfigDescriptionEntry en = (EnumConfigDescriptionEntry) entry;
        dwriter.writeTag(ConfigEditorBoot.NAMESPACE, "enum", XmlWriterSupport.OPEN); //$NON-NLS-1$

        final String[] alts = en.getOptions();
        if (alts != null)
        {
          for (int optCount = 0; optCount < alts.length; optCount++)
          {
            dwriter.writeTag(ConfigEditorBoot.NAMESPACE, "text", XmlWriterSupport.OPEN); //$NON-NLS-1$
            dwriter.writeTextNormalized(alts[optCount], false);
            dwriter.writeCloseTag();
          }
        }
        dwriter.writeCloseTag();
      }
      dwriter.writeCloseTag();
    }
    dwriter.writeCloseTag();
    writer.flush();
  }

}
TOP

Related Classes of org.pentaho.reporting.tools.configeditor.model.ConfigDescriptionModel$ConfigEntryComparator

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.