/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


package org.netbeans.modules.properties;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.openide.filesystems.FileObject;
import org.openide.loaders.MultiDataObject.Entry;
import org.openide.util.WeakListeners;


/**
 * Structure of a bundle of <code>.properties</code> files.
 * Provides structure of entries (one entry per one .properties file)
 * for one <code>PropertiesDataObject</code>.
 * <p>
 * This structure provides support for sorting entries and fast mapping
 * of integers to <code>entries</code>.
 * <p>
 * The sorting support in this class is a design flaw&nbsp;-
 * consider it deprecated.
 *
 * @author Petr Jiricka
 */
public class BundleStructure {

    /**
     * <code>PropertiesDataObject</code> whose structure is described
     * by this object
     */
    PropertiesDataObject obj;

    /**
     * file entries of the <code>PropertiesDataObject</code>.
     * The first entry always represents the primary file.
     * The other entries represent secondary files and are sorted
     * by the corresponding files' names.
     *
     * @see  #updateEntries
     */
    private PropertiesFileEntry[] entries;

    /**
     * sorted list of non-escaped keys from all entries
     *
     * @see  #buildKeySet
     */
    private List<String> keyList;
    
    /**
     * Compartor which sorts keylist.
     * Default set is sort according keys in file order.
     */
    private KeyComparator comparator = new KeyComparator();

    /**
     * registry of <code>PropertyBundleListener</code>s and support
     * for firing <code>PropertyBundleEvent</code>s.
     * Methods for registering and notification of listeners delegate to it.
     */
    private PropertyBundleSupport propBundleSupport
            = new PropertyBundleSupport(this);

    /** listens to changes on the underlying <code>PropertyDataObject</code> */
    private PropertyChangeListener propListener;

    protected BundleStructure() {
        obj = null;
    }
    /**
     * Creates a new instance describing a given
     * <code>PropertiesDataObject</code>.
     *
     * @param  obj  <code>PropertiesDataObject</code> to be desribed
     */
    public BundleStructure(PropertiesDataObject obj) {
        this.obj = obj;
        updateEntries();

        // Listen on the PropertiesDataObject.
        propListener = new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals(
                        PropertiesDataObject.PROP_FILES)) {
                    updateEntries();
                    propBundleSupport.fireBundleStructureChanged();
                }
            }
        };
        obj.addPropertyChangeListener(
                WeakListeners.propertyChange(propListener, obj));
    }

    
    /**
     * Retrieves n-th entry from the list, indexed from <code>0</code>.
     * The first entry is always the primary entry.
     *
     * @param  index  index of entry to be retrieved, starting at <code>0</code>
     * @return  entry at the specified index;
     *          or <code>null</code> if the index is out of bounds
     */
    public PropertiesFileEntry getNthEntry(int index) {
        if (entries == null) {
            notifyEntriesNotInitialized();
        }
        if (index >= 0 && index < entries.length) {
            return entries[index];
        } else {
            return null;
        }
    }

    /**
     * Retrieves an index of a file entry representing the given file.
     *
     * @param  fileName  simple name (without path and extension) of the
     *                   primary or secondary file
     * @return  index of the entry representing a file with the given filename;
     *          or <code>-1</code> if no such entry is found
     * @exception  java.lang.IllegalStateException
     *             if the list of entries has not been initialized yet
     * @see  #getEntryByFileName
     */
    public int getEntryIndexByFileName(String fileName) {
        if (entries == null) {
            notifyEntriesNotInitialized();
        }            
        for (int i = 0; i < getEntryCount(); i++) {
            if (entries[i].getFile().getName().equals(fileName)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Retrieves a file entry representing the given file
     *
     * @param  fileName  simple name (excl. path, incl. extension) of the
     *                   primary or secondary file
     * @return  entry representing the given file;
     *          or <code>null</code> if not such entry is found
     * @exception  java.lang.IllegalStateException
     *             if the list of entries has not been initialized yet
     * @see  #getEntryIndexByFileName
     */
    public PropertiesFileEntry getEntryByFileName(String fileName) {
        int index = getEntryIndexByFileName(fileName);
        return ((index == -1) ? null : entries[index]);
    }

    /**
     * Retrieves number of file entries.
     *
     * @return  number of file entries
     * @exception  java.lang.IllegalStateException
     *             if the list of entries has not been initialized yet
     */
    public int getEntryCount() {
        if (entries == null) {
            notifyEntriesNotInitialized();
        }
        return entries.length;
    }

    // Sorted keys management ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Retrieves all un-escaped keys in bundle.
     *
     * @return  sorted array of non-escaped keys
     * @exception  java.lang.IllegalStateException
     *             if the list of keys has not been initialized yet
     * @see  #sort
     */
    public String[] getKeys() {
        if (keyList == null) {
            notifyKeyListNotInitialized();
        }
        return keyList.toArray(new String[0]);
    }

    /**
     * Retrieves the n-th bundle key from the list, indexed from <code>0</code>.
     *
     * @param  keyIndex  index according to the current order of keys
     * @return  non-escaped key at the given position;
     *          or <code>null</code> if the given index is out of range
     * @exception  java.lang.IllegalStateException
     *             if the list of keys has not been initialized yet
     */
    public String keyAt(int keyIndex) {
        if (keyList == null) {
            notifyKeyListNotInitialized();
        }
        if (keyIndex < 0 || keyIndex >= keyList.size()) {
            return null;
        } else {
            return keyList.get(keyIndex);
        }
    }

    /**
     * Returns the index of the given key within the sorted list of keys
     *
     * @param  key  non-escaped key
     * @return  position of the given key in the bundle;
     *          or <code>-1</code> if the key was not found
     * @exception  java.lang.IllegalStateException
     *             if the list of keys has not been initialized yet
     */
    public int getKeyIndexByName(String key) {
        if (keyList == null) {
            notifyKeyListNotInitialized();
        }
        return keyList.indexOf(key);
    }

    /**
     * Finds a free key in the budnle. If the suggested key is not free,
     * a number is appended to it.
     */
    public String findFreeKey(String keySpec) {
        if (keyList == null) {
            notifyKeyListNotInitialized();
        }

        int n = 1;
        String key = keySpec;
        while (keyList.contains(key)) {
            key = keySpec + "_" + n++;
        }
        return key;
    }

    /**
     * Retrieves keyIndex-th key in the entryIndex-th entry from the list,
     * indexed from <code>0</code>.
     *
     * @return  item  for keyIndex-th key in the entryIndex-th entry;
     *                or <code>null</code> if the entry does not contain
     *                the key or entry doesn't exist
     */
    public Element.ItemElem getItem(int entryIndex, int keyIndex) {
        String key = keyAt(keyIndex);
        return getItem(entryIndex, key);
    }

    /**
     * Returns a property item having a given key, from a given file entry.
     *
     * @param  entryIndex  index of the file entry to get the item from
     * @param  key  key of the property to receive
     * @return  item from the given file entry, having the given key;
     *          or <code>null</code> if one of the following is true:
     *          <ul>
     *              <li>entry index is out of bounds</li>
     *              <li><code>null</code> was passed as a key</li>
     *              <li>the given key was not found in the given entry</li>
     *              <li>structure of the given file entry is not available
     *                  because of an error while reading the entry
     *                  or because parsing of the file entry was stopped
     *                  for some reason</li>
     *          </ul>
     * @see  org.netbeans.modules.properties.Element.ItemElem
     */
    public Element.ItemElem getItem(int entryIndex, String key) {
        if (key == null) {
            return null;
        }
        PropertiesFileEntry pfe = getNthEntry(entryIndex);
        if (pfe == null) {
            return null;
        }
        PropertiesStructure ps = pfe.getHandler().getStructure();
        if (ps != null) {
            return ps.getItem(key);
        } else {
            return null;
        }
    }

    /**
     * Returns property item of given key from localization corresponding to
     * given file name. If not found in given file directly then "parent" files
     * are scanned - the same way as ResourceBundle would work when asked for
     * locale specific key.
     *
     * @param localizationFile name of file entry without extension
     *        corresponding to the desired specific localization
     * @param key the key of the item in the model. See clarifications
     * {@link PropertiesStructure#getItem(java.lang.String) here}.
     * @return a property item if is it possible, otherwise {@code null}.
     */
    public Element.ItemElem getItem(String localizationFile, String key) {
        int score = 0; // number of same characters in the file name
        Element.ItemElem item = null;
        for (int i=0; i < getEntryCount(); i++) {
            PropertiesFileEntry pfe = getNthEntry(i);
            if (pfe != null) {
                String fName = pfe.getFile().getName();
                if (localizationFile.startsWith(fName)
                    && (item == null || fName.length() > score))
                {   // try to find the item in the entry with longest file name
                    // matching (most specific localization)
                    PropertiesStructure ps = pfe.getHandler().getStructure();
                    if (ps != null) {
                        Element.ItemElem it = ps.getItem(key);
                        if (it != null) {
                            item = it;
                            score = fName.length();
                        }
                    }
                }
            }
        }
        return item;
    }

    /**
     * Gets all data for given key from all locales.
     * @return String[] array of strings - repeating: locale, value, comments
     */
    public String[] getAllData(String key) {
        List<String> list = null;
        for (int i=0; i < getEntryCount(); i++) {
            PropertiesFileEntry pfe = getNthEntry(i);
            if (pfe != null) {
                PropertiesStructure ps = pfe.getHandler().getStructure();
                if (ps != null) {
                    Element.ItemElem item = ps.getItem(key);
                    if (item != null) {
                        String locale = Util.getLocaleSuffix(pfe);
                        if (list == null) {
                            list = new ArrayList<String>();
                        }
                        list.add(locale);
                        list.add(item.getValue());
                        list.add(item.getComment());
                    }
                }
            }
        }
        return list != null ? list.toArray(new String[list.size()]) : null;
    }

    public void setAllData(String key, String[] data) {
        // create missing file entries
        boolean entryCreated = false;
        for (int i=0; i < data.length; i+=3) {
            String locale = data[i];
            PropertiesFileEntry localeFile = null;
            for (int j=0; j < getEntryCount(); j++) {
                PropertiesFileEntry pfe = getNthEntry(j);
                if (pfe != null && Util.getLocaleSuffix(pfe).equals(locale)) {
                    localeFile = pfe;
                    break;
                }
            }
            if (localeFile == null) {
                Util.createLocaleFile(obj, locale.substring(1), false);
                entryCreated = true;
            }
        }
        if (entryCreated)
            updateEntries();

        // add all provided data
        for (int i=0; i < data.length; i+=3) {
            String locale = data[i];
            for (int j=0; j < getEntryCount(); j++) {
                PropertiesFileEntry pfe = getNthEntry(j);
                if (pfe != null && Util.getLocaleSuffix(pfe).equals(locale)) {
                    PropertiesStructure ps = pfe.getHandler().getStructure();
                    if (ps != null) {
                        Element.ItemElem item = ps.getItem(key);
                        if (item != null) {
                            item.setValue(data[i+1]);
                            item.setComment(data[i+2]);
                        }
                        else {
                            ps.addItem(key, data[i+1], data[i+2]);
                        }
                    }
                    break;
                }
            }
        }

        // remove superfluous data
        if (getEntryCount() > data.length/3) {
            for (int j=0; j < getEntryCount(); j++) {
                PropertiesFileEntry pfe = getNthEntry(j);
                PropertiesStructure ps = pfe.getHandler().getStructure();
                if (pfe == null || ps == null) continue;

                boolean found = false;
                for (int i=0; i < data.length; i+=3) {
                    String locale = data[i];
                    if (Util.getLocaleSuffix(pfe).equals(locale)) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    ps.deleteItem(key);
                }
            }
        }
    }

    /**
     * Returns count of all unique keys found in all file entries.
     *
     * @return  size of a union of keys from all entries
     * @exception  java.lang.IllegalStateException
     *             if the list of keys has not been initialized yet
     */
    public int getKeyCount() {
        if (keyList != null) {
            return keyList.size();
        } else {
            notifyKeyListNotInitialized();
            return 0;       //will not happen
        }
    }

    /**
     * Adds to or changes an item in specified localization file and its parents.
     */
    public void addItem(String localizationFile,
                        String key, String value, String comment,
                        boolean changeIfExists)
    {
        PropertiesStructure[] ps = getRelatedStructures(localizationFile);
        boolean changed = false;
        for (int i=0; i < ps.length; i++) {
            Element.ItemElem item = ps[i].getItem(key);
            if (item != null) {
                if (changeIfExists && !changed) {
                    item.setValue(value);
                    item.setComment(comment);
                    changed = true; // change only once - in the most specific set
                }
            }
            else {
                ps[i].addItem(key, value, comment);
                changed = true; // change only once - in the most specific set
            }
        }
    }

    /**
     * Deletes item with given key from all files of this bundle.
     */
    public void removeItem(String key) {
        for (int i=0; i < getEntryCount(); i++) {
            PropertiesFileEntry pfe = getNthEntry(i);
            if (pfe != null) {
                PropertiesStructure ps = pfe.getHandler().getStructure();
                if (ps != null) {
                    ps.deleteItem(key);
                }
            }
        }
    }

    /**
     * Sorts the keylist according the values of entry which index is given
     * to this method.
     *
     * @param  index  sorts accordinng nth-1 entry values, <code>0</code> means
     *                sort by keys, if less than <code>0</code> it re-compares
     *                keylist with the same un-changed comparator.
     */
    public void sort(int index) {
        if (index >= 0) {
            comparator.setIndex(index);
        }
        synchronized (this) {
            Collections.sort(keyList, comparator);
        }
        propBundleSupport.fireBundleDataChanged();
    }

    /**
     * Gets index accoring which is bundle key list sorted.
     *
     * @return  index, <code>0</code> means according keys,
     *                 <code>-1</code> means sorting as in default
     * properties file
     */
    public int getSortIndex() {
        return comparator.getIndex();
    }
    
    /**
     * Gets current order of sort.
     *
     * @return  true  if ascending, alse descending order
     *                (until sort index is <code>-1</code>, then unsorted)
     */
    public boolean getSortOrder() {
        return comparator.isAscending();
    }

    PropertiesOpen getOpenSupport() {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    /**
     * Builds (or rebuilds) a sorted list of entries of the underlying
     * <code>PropertiesDataObject<code> and a sorted list of keys gathered
     * from all the entries.
     *
     * @see  #entries
     * @see  #keyList
     */
    void updateEntries() {
        Map<String,PropertiesFileEntry> tm = new TreeMap<String,PropertiesFileEntry>(
                PropertiesDataObject.getSecondaryFilesComparator());
        for (Entry entry : obj.secondaryEntries()) {
            tm.put(entry.getFile().getName(), (PropertiesFileEntry) entry);
        }

        synchronized (this) {
            // Move the entries.
            int entriesCount = tm.size();
            entries = new PropertiesFileEntry[entriesCount + 1];
            entries[0] = (PropertiesFileEntry) obj.getPrimaryEntry();
            
            int index = 0;
            for (Map.Entry<String,PropertiesFileEntry> mapEntry : tm.entrySet()) {
                entries[++index] = mapEntry.getValue();
            }
        }
        buildKeySet();
    }

    /**
     * Constructs a sorted list of all keys gathered from all entries.
     *
     * @see  #keyList
     */
    protected synchronized void buildKeySet() {
        List<String> keyList = new ArrayList<String>() {
            public boolean equals(Object obj) {
                if (!(obj instanceof ArrayList)) {
                    return false;
                }
                ArrayList list2 = (ArrayList) obj;
                
                if (this.size() != list2.size()) {
                    return false;
                }
                for (int i = 0; i < this.size(); i++) {
                    if (!this.contains(list2.get(i))
                            || !list2.contains(this.get(i))) {
                        return false;
                    }
                }
                return true;
            }
        };

        //Create interim Set as ArrayList.contains is an expensive operation
        // and can cause delayes on large property files.
        // See: #188619
        Set interimSet = new HashSet<String>(keyList);
        // for all entries add all keys
        int entriesCount = getEntryCount();
        for (int index = 0; index < entriesCount; index++) {
            PropertiesFileEntry entry = getNthEntry(index);
            if (entry != null) {
                PropertiesStructure ps = entry.getHandler().getStructure();
                if (ps != null) {
                    for (Iterator<Element.ItemElem> it = ps.allItems(); it.hasNext(); ) {
                        Element.ItemElem item = it.next();
                        if (item == null) {
                            continue;
                        }
                        String key = item.getKey();
                        if (key != null) {
                            interimSet.add(key);
                        }
                    }
                }
            }
        }
        keyList.addAll(interimSet);
        Collections.sort(keyList, comparator);
        this.keyList = keyList;
    }

    /**
     * Collects PropertyStructure objects that are related for given design time
     * localization - i.e. the structure corresponding to the given file name
     * plus all the "parents". Sorted from the most specific.
     * @param localizationFile name of specific file entry (without extension)
     */
    private PropertiesStructure[] getRelatedStructures(String localizationFile) {
        List<PropertiesFileEntry> list = null;
        for (int i=0; i < getEntryCount(); i++) {
            PropertiesFileEntry pfe = getNthEntry(i);
            if (pfe != null) {
                if (localizationFile.startsWith(pfe.getFile().getName())
                        && pfe.getHandler().getStructure() != null) {
                    if (list == null) {
                        list = new ArrayList<PropertiesFileEntry>(4);
                    }
                    list.add(pfe);
                }
            }
        }
        if (list == null) {
            return new PropertiesStructure[] {};
        }
        Collections.sort(list, new Comparator<PropertiesFileEntry>() {
            public int compare(PropertiesFileEntry pfe1, PropertiesFileEntry pfe2) {
                return pfe2.getFile().getName().length() - pfe1.getFile().getName().length();
            }
        });

        PropertiesStructure[] array = new PropertiesStructure[list.size()];
        for (int i=0, n=list.size(); i < n; i++) {
            array[i] = list.get(i).getHandler().getStructure();
        }
        return array;
    }

    boolean isReadOnly() {
        boolean canWrite = false;
        for (int i=0; i < getEntryCount(); i++) {
            PropertiesFileEntry entry = getNthEntry(i);
            if (entry != null)
                canWrite |= entry.getFile().canWrite();
        }
        return !canWrite;
    }

    /**
     * Registers a given listener so that it will receive notifications
     * about changes in a property bundle.
     * If the given listener is already registered, a duplicite registration
     * will be performed, so that it will get notifications multiple times.
     *
     * @param  l  listener to be registered
     * @see  #removePropertyBundleListener
     */
    public void addPropertyBundleListener(PropertyBundleListener l) {
        if (propBundleSupport == null) propBundleSupport = new PropertyBundleSupport(this);
        propBundleSupport.addPropertyBundleListener(l);
    }

    /**
     * Unregisters a given listener so that it will no more receive
     * notifications about changes in a property bundle.
     * If the given listener has been registered multiple times,
     * only one registration item will be removed.
     *
     * @param	l		the PropertyBundleListener
     * @see  #addPropertyBundleListener
     */
    public void removePropertyBundleListener(PropertyBundleListener l) {
        propBundleSupport.removePropertyBundleListener(l);
    }

    /**
     * Notifies registered listeners of a change of a single item
     * in a single file entry.
     *
     * @param  struct  object describing the file entry
     * @param  item  changed item (within the entry)
     * @see  #addPropertyBundleListener
     */
    void notifyItemChanged(PropertiesStructure struct, Element.ItemElem item) {
        propBundleSupport.fireItemChanged(
            struct.getParent().getEntry().getFile().getName(),
            item.getKey()
        );
    }

    void notifyOneFileChanged(FileObject file) {
        // PENDING - events should be finer
        // find out whether global key table has changed and fire a change
        // according to that
        List oldKeyList = keyList;

        buildKeySet();
        if (!keyList.equals(oldKeyList)) {
            propBundleSupport.fireBundleDataChanged();
        } else {
            propBundleSupport.fireFileChanged(file.getName());
        }
    }
    /**
     * Notifies registered listeners of a change in a single file entry.
     * Depending whether a list of keys has changed, either an event
     * for a single file is fired (if the list of keys has remained unchanged)
     * or a notification of a complex change is fired.
     *
     * @param  handler  handler of an object keeping structure of the modified
     *                  file (entry)
     */
    void notifyOneFileChanged(StructHandler handler) {
        // PENDING - events should be finer
        // find out whether global key table has changed and fire a change
        // according to that
        List oldKeyList = keyList;         
        
        buildKeySet();
        if (!keyList.equals(oldKeyList)) {
            propBundleSupport.fireBundleDataChanged();
        } else {
            propBundleSupport.fireFileChanged(
                    handler.getEntry().getFile().getName());
        }
    }

    /**
     * Notifies registered listeners of a change in a single file entry.
     * The <code>Map</code> arguments are actually list of items,
     * each <code>Map</code> entry is a pair &lt;item&nbsp;key, item&gt;.
     *
     * @param  handler  handler of an object keeping structure of the modified
     *                  file (entry)
     * @param  itemsChanged  list of modified items in the entry
     * @param  itemsAdded    list of items added to the entry
     * @param  itemsDeleted  list of items removed from the entry
     */
    void notifyOneFileChanged(StructHandler handler,
                              Map<String,Element.ItemElem> itemsChanged,
                              Map<String,Element.ItemElem> itemsAdded,
                              Map<String,Element.ItemElem> itemsDeleted) {
        // PENDING - events should be finer
        // find out whether global key table has changed
        // should use a faster algorithm of building the keyset
        buildKeySet();
        propBundleSupport.fireBundleDataChanged();
    }

    /**
     * Throws a runtime exception with a message that the list of bundle keys
     * has not been initialized yet.
     *
     * @exception  java.lang.IllegalStateException  thrown always
     * @see  #buildKeySet
     */
    private void notifyKeyListNotInitialized() {
        throw new IllegalStateException(
                "Resource Bundles: KeyList not initialized");           //NOI18N
    }
    
    /**
     * Throws a runtime exception with a message that the entries
     * have not been initialized yet.
     *
     * @exception  java.lang.IllegalStateException  thrown always
     * @see  #updateEntries
     */
    private void notifyEntriesNotInitialized() {
        throw new IllegalStateException(
                "Resource Bundles: Entries not initialized");           //NOI18N
    }

    PropertiesFileEntry[] getEntries () {
        synchronized (this) {
            if (entries == null) {
                return new PropertiesFileEntry[0];
            } else {
                return Arrays.copyOf(entries, entries.length);
            }
        }
    }
    
    /**
     * Comparator which compares keys according which locale (column in table was selected).
     */
    private final class KeyComparator implements Comparator<String> {

        /** Index of column to compare with. */
        private int index;
        
        /** Flag if ascending order should be performed. */
        private boolean ascending;

        
        /** Constructor. */
        public KeyComparator() {
            this.index = -1;
            ascending = false;
        }
        
        
        /**
         * Setter for <code>index</code> property.
         * ascending -&gt; descending -&gt; primary file key order -&gt; ....
         *
         * @param  index  interval <code>0</code> .. entry count
         */
        public void setIndex(int index) {
            if (index == -1) {
                throw new IllegalArgumentException();
            }
            // if same column toggle order
            if (this.index == index) {
                if (ascending) {
                    ascending = false;
                } else {
                    // sort as in properties file
                    index = -1;
                    ascending = true;
                }
            } else {
                ascending = true;
            }
            this.index = index;
        }

        /**
         * Getter for <code>index</code> property.
         *
         * @return  <code>-1</code>..entry count, <code>-1</code> means unsorted
         * */
        public int getIndex() {
            return index;
        }
        
        /** Getter for <code>ascending</code> property. */
        public boolean isAscending() {
            return ascending;
        }

        /**
         * It's strange as it access just being compared list
         */
        public int compare(String o1, String o2) {
            String str1;
            String str2;
            
            // sort as in default properties file
            if (index < 0) {
                Element.ItemElem item1 = getItem(0, o1);
                Element.ItemElem item2 = getItem(0, o2);
                if (item1 != null && item2 != null) {
                    int i1 = item1.getBounds().getBegin().getOffset();
                    int i2 = item2.getBounds().getBegin().getOffset();
                    return i1 - i2;
                } else if (item1 != null) {
                    return -1;
                } else if (item2 != null) {
                    return 1;
                } else {
                    /*
                     * None of the keys is in the default (primary) properties
                     * file. Order the files by name.
                     */
                    str1 = o1;
                    str2 = o2;
                }
            }
            // key column
            if (index == 0) {
                str1 = o1;
                str2 = o2;
            } else {
                Element.ItemElem item1 = getItem(index - 1, o1);
                Element.ItemElem item2 = getItem(index - 1, o2);
                if (item1 == null) {
                    if (item2 == null) {
                        return 0;
                    } else {
                        return ascending ? 1 : -1;
                    }
                } else {
                    if (item2 == null) {
                        return ascending ? -1 : 1;
                    }
                }
                str1 = item1.getValue();
                str2 = item2.getValue();
            }

            if (str1 == null) {
                if (str2 == null) {
                    return 0;
                } else {
                    return ascending ? 1 : -1;
                }
            } else if (str2 == null) {
                return ascending ? -1 : 1;
            }
            int res = str1.compareToIgnoreCase(str2);

            return ascending ? res : -res;
        }
        
    } // End of inner class KeyComparator.
    
}
