/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.model.repo.api; import com.google.common.annotations.Beta; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Interner; import com.google.common.collect.Interners; import java.util.regex.Pattern; import javax.annotation.RegEx; import org.opendaylight.yangtools.concepts.Identifier; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.concepts.SemVer; import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; import org.opendaylight.yangtools.yang.common.YangConstants; /** * Base class of YANG Schema source identifiers. * * Source identifiers are designated to be carry only necessary information to * look-up YANG model source and to be used by various SchemaSourceProviders. * * (For further reference see: http://tools.ietf.org/html/rfc6020#section-5.2 * and http://tools.ietf.org/html/rfc6022#section-3.1 ). */ @Beta public abstract class SourceIdentifier implements Identifier, Immutable { /** * Default revision for sources without specified revision. This should be used for comparisons * based on revision when a SourceIdentifier does not have a revision. */ public static final String NOT_PRESENT_FORMATTED_REVISION = "0000-00-00"; @RegEx private static final String REVISION_PATTERN_STR = "\\d\\d\\d\\d-\\d\\d-\\d\\d"; /** * Simplified compiled revision pattern in format YYYY-mm-dd, which checks * only distribution of number elements. * <p> * For checking if supplied string is real date, use * {@link SimpleDateFormatUtil} instead. */ public static final Pattern REVISION_PATTERN = Pattern.compile(REVISION_PATTERN_STR); private static final Interner<SourceIdentifier> INTERNER = Interners.newWeakInterner(); private static final long serialVersionUID = 1L; private final String revision; private final String name; /** * * Creates new YANG Schema source identifier for sources without revision. * * @param name * Name of schema */ SourceIdentifier(final String name) { this.name = Preconditions.checkNotNull(name); this.revision = null; } /** * Creates new YANG Schema source identifier. * * @param name * Name of schema * @param formattedRevision * Revision of source in format YYYY-mm-dd */ SourceIdentifier(final String name, final String formattedRevision) { this.name = Preconditions.checkNotNull(name); this.revision = Preconditions.checkNotNull(formattedRevision); } /** * Creates new YANG Schema source identifier. * * @param name * Name of schema * @param formattedRevision * Revision of source in format YYYY-mm-dd. If not present, * default value will be used. */ SourceIdentifier(final String name, final Optional<String> formattedRevision) { this.name = Preconditions.checkNotNull(name); this.revision = formattedRevision.orNull(); } /** * Return an interned reference to a equivalent SemVerSourceIdentifier. * * @return Interned reference, or this object if it was interned. */ public SourceIdentifier intern() { return INTERNER.intern(this); } /** * Returns model name * * @return model name */ public String getName() { return name; } /** * Returns revision of source or null if revision was not supplied. * * @return revision of source or null if revision was not supplied. */ // FIXME: version 2.0.0: this should return Optional<String> public String getRevision() { return revision; } /** * <p> * Since we've got two ways of model versioning (revision & semantic version), * this method shouldn't be called directly anymore. Eventually, callers of this method * should be notified before method gets deleted. * @deprecated use either * <ul> * <li>{@link SemVerSourceIdentifier#create(String, SemVer)}</li> * <li>{@link SemVerSourceIdentifier#create(String, Optional, SemVer)}</li> * <li>{@link SemVerSourceIdentifier#create(String, String, SemVer)}</li> * </ul> * or * <ul> * <li>{@link RevisionSourceIdentifier#create(String)}</li> * <li>{@link RevisionSourceIdentifier#create(String, String)}</li> * <li>{@link RevisionSourceIdentifier#create(String, Optional)}</li> * </ul> * * @param moduleName * Name of schema * @param revision * Revision of source in format YYYY-mm-dd. If not present, * default value will be used. * * @return particular SourceIdentifier instance * */ @Deprecated public static SourceIdentifier create(final String moduleName, final Optional<String> revision) { return new RevisionSourceIdentifier(moduleName, revision); } /** * Returns filename for this YANG module as specified in RFC 6020. * * Returns filename in format <code>name ['@' revision] '.yang'</code> * <p> * Where revision is date in format YYYY-mm-dd. * <p> * * @see <a href="http://tools.ietf.org/html/rfc6020#section-5.2">RFC6020</a> * * @return Filename for this source identifier. */ public String toYangFilename() { final String rev = NOT_PRESENT_FORMATTED_REVISION.equals(revision) ? null : revision; return toYangFileName(name, Optional.fromNullable(rev)); } /** * Returns filename for this YANG module as specified in RFC 6020. * * Returns filename in format <code>moduleName ['@' revision] '.yang'</code> * * Where Where revision-date is in format YYYY-mm-dd. * * <p> * See http://tools.ietf.org/html/rfc6020#section-5.2 * * @return Filename for this source identifier. */ public static String toYangFileName(final String moduleName, final Optional<String> revision) { StringBuilder filename = new StringBuilder(moduleName); if (revision.isPresent()) { filename.append('@'); filename.append(revision.get()); } filename.append(YangConstants.RFC6020_YANG_FILE_EXTENSION); return filename.toString(); } }