All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xwiki.extension.AbstractExtension Maven / Gradle / Ivy

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.extension;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.ObjectUtils;
import org.xwiki.extension.internal.converter.ExtensionIdConverter;
import org.xwiki.extension.repository.ExtensionRepository;
import org.xwiki.extension.repository.ExtensionRepositoryDescriptor;
import org.xwiki.stability.Unstable;

/**
 * Base class for {@link Extension} implementations.
 *
 * @version $Id: 5e33dd3e80b6a2dd63cf0b014fcfbf782a3a943c $
 * @since 4.0M1
 */
public abstract class AbstractExtension implements MutableExtension
{
    /**
     * @see #getId()
     */
    protected ExtensionId id;

    /**
     * @see #getExtensionFeatures()
     * @deprecated since 8.0M1, use {@link #featuresMap} instead
     */
    @Deprecated
    protected Set features;

    /**
     * @see #getExtensionFeatures()
     */
    protected Map featuresMap;

    /**
     * @see #getType()
     */
    protected String type;

    /**
     * @see #getName()
     */
    protected String name;

    /**
     * @see #getLicenses()
     */
    protected List licenses;

    /**
     * @see #getSummary()
     */
    protected String summary;

    /**
     * @see #getDescription()
     */
    protected String description;

    /**
     * @see #getAuthors()
     */
    protected List authors;

    /**
     * @see #getWebSite()
     */
    protected String website;

    /**
     * @see #getAllowedNamespaces()
     */
    protected Set allowedNamespaces;

    /**
     * @see #getRepository()
     */
    protected ExtensionRepository repository;

    /**
     * @see #getProperties()
     */
    protected Map properties;

    /**
     * Used to protect properties from concurrent write;
     */
    protected ReentrantLock propertiesLock = new ReentrantLock();

    /**
     * @see #getDependencies()
     */
    protected List dependencies;

    /**
     * @see #getManagedDependencies()
     * @since 8.1M1
     */
    protected List managedDependencies;

    /**
     * @see #getScm()
     */
    protected ExtensionScm scm;

    /**
     * @see #getIssueManagement()
     */
    protected ExtensionIssueManagement issueManagement;

    /**
     * @see #getCategory()
     */
    protected String category;

    /**
     * @see #getRepositories()
     */
    protected List repositories;

    /**
     * The file of the extension.
     */
    protected ExtensionFile file;

    /**
     * @param repository the repository where this extension comes from
     * @param id the extension identifier
     * @param type the extension type
     */
    public AbstractExtension(ExtensionRepository repository, ExtensionId id, String type)
    {
        this.repository = repository;

        this.id = id;
        this.type = type;
    }

    /**
     * Create new extension descriptor by copying provided one.
     *
     * @param repository the repository where this extension comes from
     * @param extension the extension to copy
     */
    public AbstractExtension(ExtensionRepository repository, Extension extension)
    {
        this(repository, extension.getId(), extension.getType());

        set(extension);
    }

    @Override
    public void set(Extension extension)
    {
        setName(extension.getName());
        setDescription(extension.getDescription());
        setAuthors(extension.getAuthors());
        setWebsite(extension.getWebSite());
        setLicenses(extension.getLicenses());
        setSummary(extension.getSummary());
        setIssueManagement(extension.getIssueManagement());
        setScm(extension.getScm());
        setCategory(extension.getCategory());
        setExtensionFeatures(extension.getExtensionFeatures());
        setAllowedNamespaces(extension.getAllowedNamespaces());

        setDependencies(extension.getDependencies());
        setManagedDependencies(extension.getManagedDependencies());

        setProperties(extension.getProperties());
    }

    /**
     * Get an extension field by name. Fallback on properties.
     * 
     * @param fieldName the field name;
     * @return the field value or null if none could be found
     */
    @Override
    public  T get(String fieldName)
    {
        switch (fieldName.toLowerCase()) {
            case FIELD_REPOSITORY:
                return (T) getRepository();
            case FIELD_ID:
                return (T) getId().getId();
            case FIELD_VERSION:
                return (T) getId().getVersion();
            case FIELD_FEATURE:
            case FIELD_FEATURES:
                return (T) ExtensionIdConverter.toStringList(getExtensionFeatures());
            case FIELD_SUMMARY:
                return (T) getSummary();
            case FIELD_DESCRIPTION:
                return (T) getDescription();
            case FIELD_AUTHOR:
            case FIELD_AUTHORS:
                return (T) getAuthors();
            case FIELD_CATEGORY:
                return (T) getCategory();
            case FIELD_LICENSE:
            case FIELD_LICENSES:
                return (T) getLicenses();
            case FIELD_NAME:
                return (T) getName();
            case FIELD_TYPE:
                return (T) getType();
            case FIELD_WEBSITE:
                return (T) getWebSite();
            case FIELD_NAMESPACES:
            case FIELD_ALLOWEDNAMESPACE:
            case FIELD_ALLOWEDNAMESPACES:
                return (T) getAllowedNamespaces();
            case FIELD_SCM:
                return (T) getScm();
            case FIELD_REPOSITORIES:
                return (T) getRepositories();
            case FIELD_PROPERTIES:
                return (T) getProperties();

            default:
                // Unknown field, probably a property
                return getProperty(fieldName);
        }
    }

    @Override
    public ExtensionId getId()
    {
        return this.id;
    }

    /**
     * @param id the extension id
     * @see #getId()
     */
    protected void setId(ExtensionId id)
    {
        this.id = id;
    }

    @Override
    @Deprecated
    public Collection getFeatures()
    {
        return this.features != null ? this.features : Collections.emptyList();
    }

    @Override
    @Deprecated
    public void setFeatures(Collection features)
    {
        List extensionFeatures = new ArrayList(features.size());
        for (String feature : features) {
            extensionFeatures.add(new ExtensionId(feature, getId().getVersion()));
        }

        setExtensionFeatures(extensionFeatures);
    }

    @Override
    @Deprecated
    public void addFeature(String feature)
    {
        addExtensionFeature(new ExtensionId(feature, getId().getVersion()));
    }

    @Override
    public Collection getExtensionFeatures()
    {
        return this.featuresMap != null ? this.featuresMap.values() : Collections.emptyList();
    }

    @Override
    public ExtensionId getExtensionFeature(String featureId)
    {
        ExtensionId feature = null;

        // Search in the extension features
        if (this.featuresMap != null) {
            feature = this.featuresMap.get(featureId);
        }

        // Fallback on extension id
        if (feature == null && featureId.equals(getId().getId())) {
            feature = getId();
        }

        return feature;
    }

    /**
     * @since 8.0M1
     */
    @Override
    public void setExtensionFeatures(Collection features)
    {
        Map map = new LinkedHashMap<>();
        for (ExtensionId feature : features) {
            map.put(feature.getId(), feature);
        }

        setFeatureMap(map);
    }

    /**
     * @since 8.0M1
     */
    @Override
    public void addExtensionFeature(ExtensionId feature)
    {
        Map map = this.featuresMap != null
            ? new LinkedHashMap(this.featuresMap) : new LinkedHashMap();
        map.put(feature.getId(), feature);

        setFeatureMap(map);
    }

    private void setFeatureMap(Map map)
    {
        this.featuresMap = Collections.unmodifiableMap(map);

        // Retro compatibility
        Set list = new LinkedHashSet(this.featuresMap.size());
        for (ExtensionId extensionId : this.featuresMap.values()) {
            list.add(extensionId.getId());
        }
        this.features = Collections.unmodifiableSet(list);
    }

    @Override
    public String getType()
    {
        return this.type;
    }

    /**
     * @param type the type of the extension
     * @see #getType()
     */
    protected void setType(String type)
    {
        this.type = type;
    }

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

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

    @Override
    public Collection getLicenses()
    {
        return this.licenses != null ? this.licenses : Collections.emptyList();
    }

    @Override
    public void setLicenses(Collection licenses)
    {
        this.licenses = Collections.unmodifiableList(new ArrayList(licenses));
    }

    @Override
    public void addLicense(ExtensionLicense license)
    {
        List newLicenses = new ArrayList(getLicenses());
        newLicenses.add(license);

        this.licenses = Collections.unmodifiableList(newLicenses);
    }

    @Override
    public String getSummary()
    {
        return this.summary;
    }

    @Override
    public void setSummary(String summary)
    {
        this.summary = summary;
    }

    @Override
    public String getDescription()
    {
        return this.description;
    }

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

    @Override
    public List getAuthors()
    {
        return this.authors != null ? this.authors : Collections.emptyList();
    }

    @Override
    public void setAuthors(Collection authors)
    {
        this.authors = Collections.unmodifiableList(new ArrayList(authors));
    }

    @Override
    public void addAuthor(ExtensionAuthor author)
    {
        List newAuthors = new ArrayList(getAuthors());
        newAuthors.add(author);

        this.authors = Collections.unmodifiableList(newAuthors);
    }

    @Override
    public String getWebSite()
    {
        return this.website;
    }

    @Override
    public void setWebsite(String website)
    {
        this.website = website;
    }

    @Override
    public Collection getAllowedNamespaces()
    {
        return this.allowedNamespaces;
    }

    /**
     * @since 8.0M1
     */
    @Override
    public void addAllowedNamespace(String namespace)
    {
        Set newNamespaces = this.allowedNamespaces != null ? new LinkedHashSet(this.allowedNamespaces)
            : new LinkedHashSet();
        newNamespaces.add(namespace);

        this.allowedNamespaces = Collections.unmodifiableSet(newNamespaces);
    }

    /**
     * @since 8.0M1
     */
    @Override
    public void setAllowedNamespaces(Collection namespaces)
    {
        this.allowedNamespaces =
            namespaces != null ? Collections.unmodifiableSet(new LinkedHashSet<>(namespaces)) : null;
    }

    @Override
    public void addDependency(ExtensionDependency dependency)
    {
        List newDependencies = new ArrayList(getDependencies());
        newDependencies.add(dependency);

        this.dependencies = Collections.unmodifiableList(newDependencies);
    }

    @Override
    public List getDependencies()
    {
        return this.dependencies != null ? this.dependencies : Collections.emptyList();
    }

    @Override
    public void setDependencies(Collection dependencies)
    {
        this.dependencies = dependencies != null
            ? Collections.unmodifiableList(new ArrayList(dependencies)) : null;
    }

    /**
     * @since 8.1M1
     */
    @Override
    public void addManagedDependency(ExtensionDependency managedDependency)
    {
        List newManagedDependencies = new ArrayList(getManagedDependencies());
        newManagedDependencies.add(managedDependency);

        this.managedDependencies = Collections.unmodifiableList(newManagedDependencies);
    }

    @Override
    public List getManagedDependencies()
    {
        return this.managedDependencies != null ? this.managedDependencies
            : Collections.emptyList();
    }

    @Override
    public void setManagedDependencies(Collection managedDependencies)
    {
        this.managedDependencies = managedDependencies != null
            ? Collections.unmodifiableList(new ArrayList(managedDependencies)) : null;
    }

    @Override
    public ExtensionRepository getRepository()
    {
        return this.repository;
    }

    /**
     * @param repository the repository of the extension
     * @see #getRepository()
     */
    protected void setRepository(ExtensionRepository repository)
    {
        this.repository = repository;
    }

    @Override
    public ExtensionScm getScm()
    {
        return this.scm;
    }

    /**
     * @since 6.3M1
     */
    @Override
    public void setScm(ExtensionScm scm)
    {
        this.scm = scm;
    }

    @Override
    public ExtensionIssueManagement getIssueManagement()
    {
        return this.issueManagement;
    }

    /**
     * @since 6.3M1
     */
    @Override
    public void setIssueManagement(ExtensionIssueManagement issueManagement)
    {
        this.issueManagement = issueManagement;
    }

    @Override
    public ExtensionFile getFile()
    {
        return this.file;
    }

    /**
     * @param file the file of the extension
     */
    protected void setFile(ExtensionFile file)
    {
        this.file = file;
    }

    @Override
    public String getCategory()
    {
        return this.category;
    }

    /**
     * @since 7.0M2
     */
    @Unstable
    @Override
    public void setCategory(String categrory)
    {
        this.category = categrory;
    }

    @Override
    public Collection getRepositories()
    {
        return this.repositories != null ? this.repositories : Collections.emptyList();
    }

    /**
     * @since 7.3M1
     */
    @Override
    public void setRepositories(Collection repositories)
    {
        this.repositories = repositories != null ? Collections.unmodifiableList(new ArrayList<>(repositories)) : null;
    }

    /**
     * @since 7.3M1
     */
    @Override
    public void addRepository(ExtensionRepositoryDescriptor repository)
    {
        List newrepositories =
            new ArrayList(getRepositories());
        newrepositories.add(repository);

        this.repositories = Collections.unmodifiableList(newrepositories);
    }

    @Override
    public Map getProperties()
    {
        return this.properties != null ? this.properties : Collections.emptyMap();
    }

    @Override
    public  T getProperty(String key)
    {
        return (T) getProperties().get(key);
    }

    @Override
    public  T getProperty(String key, T def)
    {
        return getProperties().containsKey(key) ? (T) getProperties().get(key) : def;
    }

    @Override
    public void putProperty(String key, Object value)
    {
        synchronized (this.propertiesLock) {
            Map newProperties = new LinkedHashMap(getProperties());
            newProperties.put(key, value);

            this.properties = Collections.unmodifiableMap(newProperties);
        }
    }

    @Override
    public void setProperties(Map properties)
    {
        this.properties = Collections.unmodifiableMap(new LinkedHashMap(properties));
    }

    /**
     * @since 8.3M1
     */
    @Override
    public  T removeProperty(String key)
    {
        T previous;

        synchronized (this.propertiesLock) {
            Map newProperties = new LinkedHashMap(getProperties());
            previous = (T) newProperties.remove(key);

            this.properties = Collections.unmodifiableMap(newProperties);
        }

        return previous;
    }

    // Object

    @Override
    public String toString()
    {
        return getId().toString();
    }

    @Override
    public boolean equals(Object obj)
    {
        return this == obj || (obj instanceof Extension && getId().equals(((Extension) obj).getId()));
    }

    @Override
    public int hashCode()
    {
        return getId().hashCode();
    }

    @Override
    public int compareTo(Extension o)
    {
        if (o == null) {
            return -1;
        }

        // Try to find this into provided extension
        Integer comparizon = compareTo(this, o);
        if (comparizon != null) {
            return comparizon;
        }

        // Try to find provided extension into this
        comparizon = compareTo(o, this);
        if (comparizon != null) {
            return comparizon;
        }

        return ObjectUtils.compare(getId(), o.getId());
    }

    private static Integer compareTo(Extension e1, Extension e2)
    {
        // Try to find e1 id in e2
        ExtensionId feature = e2.getExtensionFeature(e1.getId().getId());
        if (feature != null) {
            return ObjectUtils.compare(e1.getId().getVersion(), feature.getVersion());
        }

        // Try to find e1 features in e2
        for (ExtensionId feature1 : e1.getExtensionFeatures()) {
            feature = e2.getExtensionFeature(feature1.getId());
            if (feature != null) {
                return ObjectUtils.compare(feature1.getVersion(), feature.getVersion());
            }
        }

        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy