com.enonic.cms.core.content.contentdata.custom.AbstractDataEntrySet.java Source code

Java tutorial

Introduction

Here is the source code for com.enonic.cms.core.content.contentdata.custom.AbstractDataEntrySet.java

Source

/*
 * Copyright 2000-2013 Enonic AS
 * http://www.enonic.com/license
 */
package com.enonic.cms.core.content.contentdata.custom;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.builder.HashCodeBuilder;

import com.enonic.cms.core.content.ContentKey;
import com.enonic.cms.core.content.binary.BinaryDataKey;
import com.enonic.cms.core.content.contentdata.MissingRequiredContentDataException;
import com.enonic.cms.core.content.contentdata.custom.stringbased.HtmlAreaDataEntry;
import com.enonic.cms.core.content.contenttype.CtySet;
import com.enonic.cms.core.content.contenttype.CtySetConfig;
import com.enonic.cms.core.content.contenttype.dataentryconfig.DataEntryConfig;

public abstract class AbstractDataEntrySet implements DataEntrySet {

    protected String name;

    protected String xpath;

    protected CtySet config;

    protected List<DataEntry> entries = new ArrayList<DataEntry>();

    protected List<DataEntrySet> dataEntrySetEntries = new ArrayList<DataEntrySet>();

    protected Map<String, DataEntry> entryMap = new HashMap<String, DataEntry>();

    protected DataEntryType type;

    /**
     * A shallow copy constructor.
     */
    protected AbstractDataEntrySet(AbstractDataEntrySet other) {
        this.name = other.name;
        this.xpath = other.xpath;
        this.config = other.config;
        this.entries = other.entries;
        this.dataEntrySetEntries = other.dataEntrySetEntries;
        this.entryMap = other.entryMap;
        this.type = other.type;
    }

    protected AbstractDataEntrySet(String name, DataEntryType type, String xpath) {
        this.name = name;
        this.type = type;
        this.xpath = xpath;
    }

    public String getName() {
        return name;
    }

    public String getXPath() {
        return xpath;
    }

    public DataEntryType getType() {
        return type;
    }

    public void setConfig(CtySet value) {
        this.config = value;
    }

    public CtySet getConfig() {
        return config;
    }

    public void add(DataEntry entry) {
        if (entry instanceof AbstractDataEntrySet) {
            CtySetConfig setConfig = getSetConfig(entry.getName());
            if (setConfig == null) {
                throw new IllegalArgumentException("No configuration for entry with name: " + entry.getName());
            }

            AbstractDataEntrySet dataEntrySet = (AbstractDataEntrySet) entry;
            dataEntrySet.setConfig(setConfig);
            dataEntrySetEntries.add(dataEntrySet);
        } else if (entry instanceof AbstractInputDataEntry) {
            validateEntry((AbstractInputDataEntry) entry);
        } else {
            throw new IllegalArgumentException("Unknown type of entry: " + entry.getClass().getName());
        }

        entries.add(entry);
        entryMap.put(entry.getName(), entry);
    }

    private void validateEntry(AbstractInputDataEntry entry) {
        DataEntryConfig inputConfig = getInputConfigByRelateiveXPath(entry.getXPath());

        if (inputConfig == null) {
            throw new IllegalArgumentException(
                    "No configuration for entry '" + entry.getName() + "' with xpath: " + entry.getXPath());
        }
        // Validate that entry is of same type as when you lookup in contenttype config by xpath
        if (!inputConfig.getType().isCompatible(entry.getType())) {
            throw new IllegalArgumentException(
                    "Configuration for entry '" + entry.getName() + "' not compatible. Expected "
                            + inputConfig.getType().getCompatibleDataEntryTypesAsCommaSeparatedString() + ", got "
                            + entry.getType() + ".");
        }
    }

    public int numberOfEntries() {
        return entries.size();
    }

    public List<DataEntry> getEntries() {
        return entries;
    }

    public boolean hasValue() {
        /* Groups has allways value */
        return true;
    }

    public boolean breaksRequiredContract() {
        // No required contract on sets (groups), so it cant break!
        return false;
    }

    public List<DataEntry> getEntries(DataEntryType type) {
        List<DataEntry> entriesOfType = new ArrayList<DataEntry>();
        for (DataEntry entry : entries) {
            if (entry.getType() == type) {
                entriesOfType.add(entry);
            }
        }
        return entriesOfType;
    }

    public List<DataEntry> getNonNullEntries() {
        List<DataEntry> noNullEntriesOfType = new ArrayList<DataEntry>();
        for (DataEntry entry : entries) {
            if (entry.hasValue()) {
                noNullEntriesOfType.add(entry);
            }
        }
        return noNullEntriesOfType;
    }

    public List<DataEntry> getNonNullEntries(DataEntryType type) {
        List<DataEntry> allEntriesOfType = getEntries(type);
        List<DataEntry> noNullEntriesOfType = new ArrayList<DataEntry>();
        for (DataEntry entry : allEntriesOfType) {
            if (entry.hasValue()) {
                noNullEntriesOfType.add(entry);
            }
        }
        return noNullEntriesOfType;
    }

    public DataEntry getEntry(String name) {
        DataEntry dataEntry = entryMap.get(name);
        if (dataEntry != null) {
            return dataEntry;
        }

        // if not found on this level, look thru the data entry sets
        for (DataEntrySet dataEntrySet : dataEntrySetEntries) {
            dataEntry = dataEntrySet.getEntry(name);
            if (dataEntry != null) {
                return dataEntry;
            }
        }

        return null;
    }

    public boolean hasGroupDataEntry(String name, int groupIndex) {
        GroupDataEntry existing = getGroupDataEntry(name, groupIndex);
        return existing != null;
    }

    public GroupDataEntry getGroupDataEntry(String name, int groupIndex) {
        for (DataEntry dataEntry : getEntries()) {
            if (dataEntry instanceof GroupDataEntry) {
                GroupDataEntry groupDataEntry = (GroupDataEntry) dataEntry;

                if (groupDataEntry.getName().equals(name) && groupDataEntry.getGroupIndex() == groupIndex) {
                    return groupDataEntry;
                }
            }
        }

        return null;
    }

    public Set<ContentKey> resolveRelatedContentKeys() {
        Set<ContentKey> keys = new HashSet<ContentKey>();

        for (DataEntry entry : getEntries()) {
            if (entry instanceof RelationDataEntry) {
                final ContentKey contentKey = ((RelationDataEntry) entry).getContentKey();
                if (contentKey != null) {
                    keys.add(contentKey);
                }
            } else if (entry instanceof RelationsDataEntry) {
                keys.addAll(((RelationsDataEntry) entry).getRelatedContentKeys());
            } else if (entry instanceof DataEntrySet) {
                keys.addAll(((DataEntrySet) entry).resolveRelatedContentKeys());
            } else if (entry instanceof HtmlAreaDataEntry) {
                keys.addAll(((HtmlAreaDataEntry) entry).resolveRelatedContentKeys());
            }
        }

        return keys;
    }

    public boolean hasRelatedChild(ContentKey contentKey) {
        return resolveRelatedContentKeys().contains(contentKey);
    }

    /**
     * marks references in XML ContentData as deleted.
     * <p/>
     * this function will be overridden in CustomContentData and called from ContentData interface
     * required to be here because also it is required for GroupDataEntry too
     *
     * @param key reference to content has to be removed
     * @return true if something is removed
     */
    public boolean markReferencesToContentAsDeleted(ContentKey key) {
        boolean marked = false;

        for (final DataEntry entry : this.entries) {
            // File, Image, RelatedContentDataEntry
            if (entry instanceof RelationDataEntry) {
                final RelationDataEntry relatedContentDataEntry = (RelationDataEntry) entry;
                if (key.equals(relatedContentDataEntry.getContentKey())) {
                    if (!relatedContentDataEntry.isMarkedAsDeleted()) {
                        relatedContentDataEntry.markAsDeleted();
                        marked = true;
                    }
                }
            }

            // Files, Images, RelatedContentsDataEntry
            else if (entry instanceof RelationsDataEntry) {
                final RelationsDataEntry relationsDataEntry = (RelationsDataEntry) entry;
                marked = relationsDataEntry.markReferencesToContentAsDeleted(key) || marked;
            }

            // Group
            else if (entry instanceof AbstractDataEntrySet) {
                final AbstractDataEntrySet dataEntrySet = (AbstractDataEntrySet) entry;
                marked = dataEntrySet.markReferencesToContentAsDeleted(key) || marked;
            }
        }

        return marked;
    }

    public List<BinaryDataEntry> getBinaryDataEntryList() {

        List<BinaryDataEntry> entries = new ArrayList<BinaryDataEntry>();
        for (DataEntry entry : getEntries()) {
            if (entry instanceof BinaryDataEntry) {
                entries.add((BinaryDataEntry) entry);
            } else if (entry instanceof DataEntrySet) {
                entries.addAll(((DataEntrySet) entry).getBinaryDataEntryList());
            }
        }
        return entries;
    }

    public boolean hasBinaryDataEntry(BinaryDataEntry subject) {

        for (DataEntry entry : getEntries()) {
            if (entry instanceof BinaryDataEntry) {
                BinaryDataEntry binaryDataEntry = (BinaryDataEntry) entry;
                if (binaryDataEntry.hasExistingBinaryKey()
                        && binaryDataEntry.getExistingBinaryKey().equals(subject.getExistingBinaryKey())) {
                    return true;
                }
            } else if (entry instanceof DataEntrySet) {
                if (((DataEntrySet) entry).hasBinaryDataEntry(subject)) {
                    return true;
                }
            }
        }
        return false;
    }

    public void replaceBinaryKeyPlaceholders(List<BinaryDataKey> binaryDatas) {
        for (DataEntry entry : getEntries()) {
            if (entry instanceof BinaryDataEntry) {
                BinaryDataEntry binaryDataEntry = (BinaryDataEntry) entry;
                if (binaryDataEntry.hasBinaryKeyPlaceholder()) {
                    String placeHolder = binaryDataEntry.getBinaryKeyPlaceholder();
                    int index = Integer.valueOf(placeHolder.substring(1));
                    BinaryDataKey key = binaryDatas.get(index);
                    binaryDataEntry.setExistingBinaryKey(key.toInt());
                }
            } else if (entry instanceof DataEntrySet) {
                ((DataEntrySet) entry).replaceBinaryKeyPlaceholders(binaryDatas);
            }
        }
    }

    public void turnBinaryKeysIntoPlaceHolders(Map<BinaryDataKey, Integer> indexByBinaryDataKey) {
        for (DataEntry entry : getEntries()) {
            if (entry instanceof BinaryDataEntry) {
                BinaryDataEntry binaryDataEntry = (BinaryDataEntry) entry;
                if (binaryDataEntry.hasExistingBinaryKey()) {
                    BinaryDataKey binaryDataKey = new BinaryDataKey(binaryDataEntry.getExistingBinaryKey());
                    Integer index = indexByBinaryDataKey.get(binaryDataKey);
                    if (index != null) {
                        binaryDataEntry.setExistingBinaryKey(null);
                        binaryDataEntry.setBinaryKeyPlaceholder("%" + index);
                    }
                }
            } else if (entry instanceof DataEntrySet) {
                ((DataEntrySet) entry).turnBinaryKeysIntoPlaceHolders(indexByBinaryDataKey);
            }
        }
    }

    public List<GroupDataEntry> getGroupDataSets(final String name) {
        final List<GroupDataEntry> groupDatasets = new ArrayList<GroupDataEntry>();
        for (final DataEntry entry : entries) {
            if (entry instanceof GroupDataEntry) {
                final GroupDataEntry groupDataEntry = (GroupDataEntry) entry;
                if (name.equals(groupDataEntry.getName())) {
                    groupDatasets.add(groupDataEntry);
                }
            }
        }
        return groupDatasets;
    }

    public DataEntryConfig getInputConfig(String name) {
        return config.getInputConfig(name);
    }

    public DataEntryConfig getInputConfigByRelateiveXPath(String relativeXpath) {
        return config.getInputConfigByRelativeXPath(relativeXpath);
    }

    public CtySet getContentTypeConfig() {
        return config;
    }

    public CtySetConfig getSetConfig(String name) {
        return config.getSetConfig(name);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof AbstractDataEntrySet)) {
            return false;
        }

        AbstractDataEntrySet that = (AbstractDataEntrySet) o;
        if (!equalsEntriesOrder(this.getNonNullEntries(DataEntryType.GROUP),
                that.getNonNullEntries(DataEntryType.GROUP))) {
            return false;
        }

        if (!equalsEntriesIgnoreOrder(this.getNonNullEntries(), that.getNonNullEntries())) {
            return false;
        }

        return true;
    }

    private boolean equalsEntriesOrder(List<DataEntry> entriesA, List<DataEntry> entriesB) {
        if (entriesA.size() != entriesB.size()) {
            return false;
        }

        int i = 0;
        for (DataEntry entryA : entriesA) {
            final DataEntry entryB = entriesB.get(i++);
            if (!entryA.equals(entryB)) {
                return false;
            }
        }

        return true;
    }

    private boolean equalsEntriesIgnoreOrder(List<DataEntry> entriesA, List<DataEntry> entriesB) {
        if (entriesA.size() != entriesB.size()) {
            return false;
        }

        for (DataEntry entryA : entriesA) {
            if (!entriesB.contains(entryA)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        final HashCodeBuilder builder = new HashCodeBuilder(241, 459).appendSuper(super.hashCode());
        for (DataEntry entry : entries) {
            builder.append(entry);
        }
        return builder.toHashCode();
    }

    protected void validateRequiredDataEntry(final DataEntryConfig dataEntryConfig, final DataEntry dataEntry) {
        if (dataEntry == null) {
            throw MissingRequiredContentDataException.missingDataEntry(dataEntryConfig);
        } else if (!dataEntry.hasValue()) {
            throw MissingRequiredContentDataException.missingDataEntryValue(dataEntryConfig);
        } else if (dataEntry.breaksRequiredContract()) {
            throw MissingRequiredContentDataException.missingDataEntryValue(dataEntryConfig);
        }
    }
}