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

org.jvnet.hk2.component.DescriptorImpl Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package org.jvnet.hk2.component;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;

import org.glassfish.hk2.Descriptor;
import org.glassfish.hk2.Scope;

/**
 * A simple Descriptor.  FOR INTERNAL USE ONLY.
 * 
 * @author Jerome Dochez
 * @author Jeff Trent
 */
public class DescriptorImpl implements Descriptor {

    private final LinkedHashSet names;
    private final String typeName;
    private final LinkedHashSet qualifiers;
    private final LinkedHashSet contracts;
    private final MultiMap metadata;
    private final Scope scope;
    
    private boolean readOnly;

    public DescriptorImpl() {
        this(null, null, null, null);
    }
    
    public DescriptorImpl(Class type) {
        this(null, type.getName(), null, null);
    }
    
    public DescriptorImpl(String name, String typeName) {
        this(name, typeName, null, null);
    }
    
    public DescriptorImpl(String name, String typeName, MultiMap metadata, Scope scope) {
        this(null, typeName, metadata, scope, null, null);
        if (null != name) {
            addName(name);
        }
    }
    
    public DescriptorImpl(Descriptor other) {
        this(other, false);
    }
    
    public DescriptorImpl(Descriptor other, boolean readOnly) {
        this.names = new LinkedHashSet(other.getNames());
        this.typeName = other.getTypeName();
        this.scope = (Scope) other.getScope();
        this.qualifiers = new LinkedHashSet(other.getQualifiers());
        this.contracts = new LinkedHashSet(other.getContracts());
        if (null == other.getMetadata() || MultiMap.emptyMap() == (Object)other.getMetadata()) {
            this.metadata = MultiMap.emptyMap();
        } else {
            this.metadata = new MultiMap(other.getMetadata());
        }
        
        if (readOnly) {
            setReadOnly();
        }
    }
    
    private DescriptorImpl(LinkedHashSet names,
            String typeName,
            MultiMap metadata,
            Scope scope,
            LinkedHashSet qualifiers,
            LinkedHashSet contracts) {
        this.names = (null == names) ? new LinkedHashSet() : names;
        this.typeName = typeName;
        this.scope = scope;
        this.qualifiers = (null == qualifiers) ? new LinkedHashSet() : qualifiers;
        this.contracts = (null == contracts) ? new LinkedHashSet() : contracts;
        this.metadata = (null == metadata) ? new MultiMap() : metadata;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        append(sb, "names", names);
        append(sb, "typeName", typeName);
        append(sb, "scope", scope);
        append(sb, "qualifiers", qualifiers);
        append(sb, "contracts", contracts);
        append(sb, "metadata", metadata);
        return sb.toString();
    }
    
    @Override
    public int hashCode() {
        return (null == typeName) ? -1 : typeName.hashCode();
    }
    
    @Override
    public boolean equals(Object another) {
        if (!Descriptor.class.isInstance(another)) {
            return false;
        }

        Descriptor d = Descriptor.class.cast(another);
        
        return equals(getNames(), d.getNames()) 
            && equals(getTypeName(), d.getTypeName())
            && equals(getMetadata(), d.getMetadata())
            && equals(getScope(), d.getScope())
            && equals(getContracts(), d.getContracts())
            && equals(getQualifiers(), d.getQualifiers());
    }
    
    private void append(StringBuilder sb, String key, Object val) {
        if (null != val) {
            if (sb.length() > 0) {
                sb.append(",");
            }
            sb.append(key).append("=").append(val);
        }
    }

    public void setReadOnly() {
        this.readOnly = true;
    }
    
    protected void assertNotReadOnly() {
        if (readOnly) {
            throw new IllegalStateException();
        }
    }

    public DescriptorImpl addName(String name) {
        assertNotReadOnly();
        names.add(name);
        return this;
    }

    public DescriptorImpl addContract(Class clazz) {
        return addContract(clazz.getName());
    }
    
    public DescriptorImpl addContract(String contractFQCN) {
        assertNotReadOnly();
        contracts.add(contractFQCN);
        return this;
    }

    public DescriptorImpl addQualifierType(String annotation) {
        assertNotReadOnly();
        qualifiers.add(annotation);
        return this;
    }

    public DescriptorImpl addMetadata(String key, String value) {
        assertNotReadOnly();
        metadata.add(key, value);
        return this;
    }
    
    @Override
    public Collection getNames() {
        return Collections.unmodifiableSet(names);
    }

    @Override
    public org.glassfish.hk2.Scope getScope() {
        return scope;
    }

    @Override
    public MultiMap getMetadata() {
        return metadata.readOnly();
    }

    @Override
    public Collection getQualifiers() {
        return Collections.unmodifiableSet(qualifiers);
    }

    @Override
    public Collection getContracts() {
        return Collections.unmodifiableSet(contracts);
    }

    @Override
    public boolean hasName(String name) {
        return names.contains(name);
    }
    
    @Override
    public boolean hasQualifier(String qualifier) {
        return qualifiers.contains(qualifier);
    }

    @Override
    public boolean hasContract(String contract) {
        return contracts.contains(contract);
    }

    @Override
    public String getTypeName() {
        return typeName;
    }
    
    /**
     * Returns true if this instance "matches" another instance.
     * 
     * 

* Matching considers each attribute of the descriptor one by one. * For non-null attributes, equality checks are made. If the this * instance contains a null value (or empty for the case for collections) * then the result for that field is true as well. For non-null and non- * empty collections, this instance must be a proper subset of the * other. * * @param another the other Descriptor to compare against * @return true if all fields in this instance matches another */ public boolean matches(Descriptor another) { return matches(this, another); } public static boolean matches(Descriptor d1, Descriptor d2) { if (null == d1 && null == d2) { return true; } if (null == d1 || null == d2) { return false; } return matches(d1.getNames(), d2.getNames()) && matches(d1.getTypeName(), d2.getTypeName()) && matches(d1.getScope(), d2.getScope()) && matches(d1.getQualifiers(), d2.getQualifiers()) && matches(d1.getContracts(), d2.getContracts()) && matches(d1.getMetadata(), d2.getMetadata()); } @SuppressWarnings("unchecked") private static boolean matches(Object o1, Object o2) { if (null == o1) { return true; } if (Collection.class.isInstance(o1)) { Collection c1 = Collection.class.cast(o1); if (Collection.class.isInstance(o2)) { return matches(c1, Collection.class.cast(o2)); } } else if (MultiMap.class.isInstance(o1) && org.glassfish.hk2.MultiMap.class.isInstance(o2)) { return MultiMap.class.cast(o1).matches(org.glassfish.hk2.MultiMap.class.cast(o2)); } return equals(o1, o2); } private static boolean matches(Collection c1, Collection c2) { if (null == c1 && null == c2) { return true; } if (null == c1 || null == c2) { return false; } if (c1.size() > c2.size()) { return false; } for (Object o : c1) { if (!c2.contains(o)) { return false; } } return true; } public static boolean isEmpty(Descriptor descriptor) { if (null == descriptor || EMPTY_DESCRIPTOR == descriptor) { return true; } if (!isEmpty(descriptor.getNames()) || !isEmpty(descriptor.getTypeName())) { return false; } if (!isEmpty(descriptor.getContracts()) || ! isEmpty(descriptor.getQualifiers())) { return false; } if (null != descriptor.getMetadata() && descriptor.getMetadata().size() > 0) { return false; } if (null != descriptor.getScope()) { return false; } return true; } static boolean isEmpty(Collection coll) { return (null == coll || coll.isEmpty()); } static boolean isEmpty(String val) { return (null == val || val.isEmpty()); } private static boolean equals(Object o1, Object o2) { if (null == o1 && null == o2) { return true; } if (null == o1 || null == o2) { return false; } if (o1.getClass() != o2.getClass()) { if (Collection.class.isInstance(o1)) { Collection c1 = Collection.class.cast(o1); Collection c2 = Collection.class.cast(o2); if (c1.size() != c2.size()) { return false; } Iterator it1 = c1.iterator(); Iterator it2 = c2.iterator(); while (it1.hasNext()) { if (!it1.next().equals(it2.next())) { return false; } } return true; } } return o1.equals(o2); } public static DescriptorImpl createMerged(Descriptor d1, Descriptor d2) { if (null == d1 && null == d2) { return null; } if (null == d1) { return new DescriptorImpl(d2); } if (null == d2) { return new DescriptorImpl(d1); } LinkedHashSet names = getMergedSet(d1.getNames(), d2.getNames()); String typeName = getMerged(d1.getTypeName(), d2.getTypeName()); Scope scope = (Scope) getMerged(d1.getScope(), d2.getScope()); MultiMap metadata = getMergedMetaData(d1.getMetadata(), d2.getMetadata()); LinkedHashSet qualifiers = getMergedSet(d1.getQualifiers(), d2.getQualifiers()); LinkedHashSet contracts = getMergedSet(d1.getContracts(), d2.getContracts()); return new DescriptorImpl(names, typeName, metadata, scope, qualifiers, contracts); } private static MultiMap getMergedMetaData( org.glassfish.hk2.MultiMap m1, org.glassfish.hk2.MultiMap m2) { if (null == m1 && null == m2) { return null; } MultiMap mm = new MultiMap(); if (null != m1) { mm.mergeAll(m1); } if (null != m2) { mm.mergeAll(m2); } return mm; } private static LinkedHashSet getMergedSet(Collection s1, Collection s2) { if (null == s1 && null == s2) { return null; } LinkedHashSet set = new LinkedHashSet(); if (null != s1) { set.addAll(s1); } if (null != s2) { set.addAll(s2); } return set; } static T getMerged(T v1, T v2) { if (null == v1) { return v2; } if (null == v2) { return v1; } if (!v1.equals(v2)) { throw new IllegalStateException("can't merge " + v1 + " and " + v2); } return v1; } final static Descriptor EMPTY_DESCRIPTOR = new Descriptor() { @Override public Collection getNames() { return Collections.emptySet(); } @Override public MultiMap getMetadata() { return org.jvnet.hk2.component.MultiMap.emptyMap(); } @Override public Collection getQualifiers() { return Collections.emptySet(); } @Override public Collection getContracts() { return Collections.emptySet(); } @Override public String getTypeName() { return null; } @Override public org.glassfish.hk2.Scope getScope() { return null; } @Override public boolean hasName(String name) { return false; } @Override public boolean hasQualifier(String qualifier) { return false; } @Override public boolean hasContract(String contract) { return false; } }; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy