001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.eclipse.aether.metadata;
020
021import java.io.File;
022import java.util.Collections;
023import java.util.HashMap;
024import java.util.Map;
025import java.util.Objects;
026
027/**
028 * A skeleton class for metadata.
029 */
030public abstract class AbstractMetadata implements Metadata {
031
032    private Metadata newInstance(Map<String, String> properties, File file) {
033        return new DefaultMetadata(
034                getGroupId(), getArtifactId(), getVersion(), getType(), getNature(), file, properties);
035    }
036
037    public Metadata setFile(File file) {
038        File current = getFile();
039        if (Objects.equals(current, file)) {
040            return this;
041        }
042        return newInstance(getProperties(), file);
043    }
044
045    public Metadata setProperties(Map<String, String> properties) {
046        Map<String, String> current = getProperties();
047        if (current.equals(properties) || (properties == null && current.isEmpty())) {
048            return this;
049        }
050        return newInstance(copyProperties(properties), getFile());
051    }
052
053    public String getProperty(String key, String defaultValue) {
054        String value = getProperties().get(key);
055        return (value != null) ? value : defaultValue;
056    }
057
058    /**
059     * Copies the specified metadata properties. This utility method should be used when creating new metadata instances
060     * with caller-supplied properties.
061     *
062     * @param properties The properties to copy, may be {@code null}.
063     * @return The copied and read-only properties, never {@code null}.
064     */
065    protected static Map<String, String> copyProperties(Map<String, String> properties) {
066        if (properties != null && !properties.isEmpty()) {
067            return Collections.unmodifiableMap(new HashMap<>(properties));
068        } else {
069            return Collections.emptyMap();
070        }
071    }
072
073    @Override
074    public String toString() {
075        StringBuilder buffer = new StringBuilder(128);
076        if (getGroupId().length() > 0) {
077            buffer.append(getGroupId());
078        }
079        if (getArtifactId().length() > 0) {
080            buffer.append(':').append(getArtifactId());
081        }
082        if (getVersion().length() > 0) {
083            buffer.append(':').append(getVersion());
084        }
085        buffer.append('/').append(getType());
086        return buffer.toString();
087    }
088
089    /**
090     * Compares this metadata with the specified object.
091     *
092     * @param obj The object to compare this metadata against, may be {@code null}.
093     * @return {@code true} if and only if the specified object is another {@link Metadata} with equal coordinates,
094     *         type, nature, properties and file, {@code false} otherwise.
095     */
096    @Override
097    public boolean equals(Object obj) {
098        if (obj == this) {
099            return true;
100        } else if (!(obj instanceof Metadata)) {
101            return false;
102        }
103
104        Metadata that = (Metadata) obj;
105
106        return Objects.equals(getArtifactId(), that.getArtifactId())
107                && Objects.equals(getGroupId(), that.getGroupId())
108                && Objects.equals(getVersion(), that.getVersion())
109                && Objects.equals(getType(), that.getType())
110                && Objects.equals(getNature(), that.getNature())
111                && Objects.equals(getFile(), that.getFile())
112                && Objects.equals(getProperties(), that.getProperties());
113    }
114
115    /**
116     * Returns a hash code for this metadata.
117     *
118     * @return A hash code for the metadata.
119     */
120    @Override
121    public int hashCode() {
122        int hash = 17;
123        hash = hash * 31 + getGroupId().hashCode();
124        hash = hash * 31 + getArtifactId().hashCode();
125        hash = hash * 31 + getType().hashCode();
126        hash = hash * 31 + getNature().hashCode();
127        hash = hash * 31 + getVersion().hashCode();
128        hash = hash * 31 + hash(getFile());
129        return hash;
130    }
131
132    private static int hash(Object obj) {
133        return (obj != null) ? obj.hashCode() : 0;
134    }
135}