org.kuali.rice.krad.data.metadata.impl.MetadataCommonBase.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.rice.krad.data.metadata.impl.MetadataCommonBase.java

Source

/**
 * Copyright 2005-2014 The Kuali Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
 *
 * 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.kuali.rice.krad.data.metadata.impl;

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

import org.apache.commons.lang.StringUtils;
import org.kuali.rice.krad.data.metadata.DataObjectAttribute;
import org.kuali.rice.krad.data.metadata.MetadataCommon;
import org.kuali.rice.krad.data.metadata.MetadataMergeAction;

/**
 * Class defining common attributes on many different components of the metadata (data objects, attributes, etc...)
 * 
 * @author Kuali Rice Team (rice.collab@kuali.org)
 */
public abstract class MetadataCommonBase implements MetadataCommonInternal {
    private static final long serialVersionUID = 2610090812919046672L;
    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MetadataCommonBase.class);

    protected MetadataCommon embeddedCommonMetadata;
    protected MetadataMergeAction mergeAction = MetadataMergeAction.MERGE;

    protected String backingObjectName;
    protected String name;
    protected String label;
    protected String shortLabel;
    protected String description;
    protected Boolean readOnly = false;

    /**
     * Returns the object's name without relying on embedded metadata. To override, this name must be set.
     */
    @Override
    public Object getUniqueKeyForMerging() {
        return name;
    }

    @Override
    public String getBackingObjectName() {
        if (backingObjectName != null) {
            return backingObjectName;
        }
        if (embeddedCommonMetadata != null) {
            return embeddedCommonMetadata.getBackingObjectName();
        }
        return getName();
    }

    public void setBackingObjectName(String backingObjectName) {
        this.backingObjectName = backingObjectName;
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getLabel() {
        // locally set
        if (label != null) {
            return label;
        }
        // we have an embedded, check it's label
        if (embeddedCommonMetadata != null) {
            return embeddedCommonMetadata.getLabel();
        }
        return getLabelFromPropertyName(name);
    }

    public void setLabel(String label) {
        this.label = label;
    }

    @Override
    public String getShortLabel() {
        // locally set
        if (StringUtils.isNotBlank(shortLabel)) {
            return shortLabel;
        }
        // we have an embedded, check it's short label
        if (embeddedCommonMetadata != null) {
            return embeddedCommonMetadata.getShortLabel();
        }
        // default to the label (local or embedded)
        return getLabel();
    }

    public void setShortLabel(String shortLabel) {
        this.shortLabel = shortLabel;
    }

    @Override
    public String getDescription() {
        if (description != null) {
            return description;
        }
        if (embeddedCommonMetadata != null) {
            return embeddedCommonMetadata.getDescription();
        }
        return "";
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public boolean isReadOnly() {
        if (readOnly != null) {
            return readOnly;
        }
        if (embeddedCommonMetadata != null) {
            return embeddedCommonMetadata.isReadOnly();
        }
        return false;
    }

    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(this.getClass().getSimpleName()).append(" [");
        builder.append("name=").append(getName()).append(", ");
        builder.append("label=").append(getLabel()).append(", ");
        builder.append("backingObjectName=").append(getBackingObjectName()).append(", ");
        builder.append("readOnly=").append(isReadOnly());
        builder.append(", ").append("mergeAction=").append(mergeAction);
        builder.append("]");
        return builder.toString();
    }

    /**
    * Parses the label from the property name.
    *
    * @param propertyName the full property name including separators
    */
    protected String getLabelFromPropertyName(String propertyName) {
        // We only want to include the component after the last property separator
        if (propertyName.contains(".")) {
            propertyName = StringUtils.substringAfterLast(propertyName, ".");
        }
        StringBuilder label = new StringBuilder(propertyName);
        // upper case the 1st letter
        label.replace(0, 1, label.substring(0, 1).toUpperCase());
        // loop through, inserting spaces when cap
        for (int i = 0; i < label.length(); i++) {
            if (Character.isUpperCase(label.charAt(i)) || Character.isDigit(label.charAt(i))) {
                label.insert(i, ' ');
                i++;
            }
        }

        return label.toString().trim();
    }

    @Override
    public MetadataCommon getEmbeddedCommonMetadata() {
        return embeddedCommonMetadata;
    }

    @Override
    public void setEmbeddedCommonMetadata(MetadataCommon embeddedCommonMetadata) {
        this.embeddedCommonMetadata = embeddedCommonMetadata;
    }

    @Override
    public MetadataMergeAction getMergeAction() {
        return mergeAction;
    }

    public void setMergeAction(MetadataMergeAction mergeAction) {
        this.mergeAction = mergeAction;
    }

    /**
    * Merges multiple lists into one.
    *
    * <p>
    *     Merges embedded and locallists.
    * </p>
    *
    * @param embeddedList the embedded list.
    * @param localList the local list.
    */
    protected <T extends MetadataCommon> List<T> mergeLists(List<T> embeddedList, List<T> localList) {
        if (localList == null) {
            return new ArrayList<T>(embeddedList);
        }
        List<T> mergedList = new ArrayList<T>(embeddedList.size() + localList.size());
        // Go through the local list (which can override the embedded list and add to a map by name)
        Map<Object, T> localObjectMap = new HashMap<Object, T>(localList.size());
        for (T item : localList) {
            if (item instanceof MetadataCommonInternal) {
                localObjectMap.put(((MetadataCommonInternal) item).getUniqueKeyForMerging(), item);
            } else {
                localObjectMap.put(item.getName(), item);
            }
        }
        // Go through Master (to be embedded) list - add to merged list
        for (T item : embeddedList) {
            Object mergeKey = item.getName();
            if (item instanceof MetadataCommonInternal) {
                mergeKey = ((MetadataCommonInternal) item).getUniqueKeyForMerging();
            }
            // check for key match in local list
            T localItem = localObjectMap.get(mergeKey);
            // if no match, add to list
            if (localItem == null) {
                mergedList.add(item);
            } else {
                if (localItem.getMergeAction() == MetadataMergeAction.MERGE) {
                    // add the master item as embedded in the local item
                    if (localItem instanceof MetadataCommonInternal) {
                        ((MetadataCommonInternal) localItem).setEmbeddedCommonMetadata(item);
                        if (localItem instanceof DataObjectAttributeInternal
                                && item instanceof DataObjectAttribute) {
                            ((DataObjectAttributeInternal) localItem)
                                    .setEmbeddedAttribute((DataObjectAttribute) item);
                        }
                    } else {
                        LOG.warn("List item implementation class (" + localItem.getClass().getName()
                                + ") does not implement the MetadataCommonInternal interface.  It can not merge in previously extracted metadata.");
                    }
                    // add the local item to the list
                    mergedList.add(localItem);
                } else if (localItem.getMergeAction() == MetadataMergeAction.REPLACE) {
                    // use the local metadata and do not embed
                    mergedList.add(localItem);
                } else if (localItem.getMergeAction() == MetadataMergeAction.REMOVE) {
                    // Do nothing - just don't add to the list
                } else if (localItem.getMergeAction() == MetadataMergeAction.NO_OVERRIDE) {
                    // Ignore the overriding item and add the original
                    mergedList.add(item);
                } else {
                    LOG.warn("Unsupported MetadataMergeAction: " + localItem.getMergeAction() + " on " + localItem);
                }
                // remove the item from the map since it's been merged
                localObjectMap.remove(mergeKey);
            }
        }
        // now, the map only has the remaining items - add them to the end of the list
        mergedList.addAll(localObjectMap.values());

        return mergedList;
    }
}