/*
* 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 static com.google.common.base.Preconditions.checkArgument;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.io.ByteSource;
import com.google.common.io.Resources;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Map.Entry;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.common.YangNames;
/**
* YANG text schema source representation. Exposes an RFC6020 or RFC7950 text representation
* as an {@link InputStream}.
*/
@Beta
public abstract class YangTextSchemaSource extends ByteSource implements YangSchemaSourceRepresentation {
private final SourceIdentifier identifier;
protected YangTextSchemaSource(final SourceIdentifier identifier) {
this.identifier = Preconditions.checkNotNull(identifier);
}
public static SourceIdentifier identifierFromFilename(final String name) {
checkArgument(name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION),
"Filename %s does not have a .yang extension", name);
final String baseName = name.substring(0, name.length() - YangConstants.RFC6020_YANG_FILE_EXTENSION.length());
final Entry<String, String> parsed = YangNames.parseFilename(baseName);
return RevisionSourceIdentifier.create(parsed.getKey(), Optional.fromNullable(parsed.getValue()));
}
/**
* Create a new YangTextSchemaSource with a specific source identifier and backed
* by ByteSource, which provides the actual InputStreams.
*
* @param identifier SourceIdentifier of the resulting schema source
* @param delegate Backing ByteSource instance
* @return A new YangTextSchemaSource
*/
public static YangTextSchemaSource delegateForByteSource(final SourceIdentifier identifier,
final ByteSource delegate) {
return new DelegatedYangTextSchemaSource(identifier, delegate);
}
/**
* Create a new YangTextSchemaSource with {@link SourceIdentifier} derived from a supplied filename and backed
* by ByteSource, which provides the actual InputStreams.
*
* @param fileName File name
* @param delegate Backing ByteSource instance
* @return A new YangTextSchemaSource
* @throws IllegalArgumentException if the file name has invalid format
*/
public static YangTextSchemaSource delegateForByteSource(final String fileName, final ByteSource delegate) {
return new DelegatedYangTextSchemaSource(identifierFromFilename(fileName), delegate);
}
/**
* Create a new YangTextSchemaSource backed by a {@link File} with {@link SourceIdentifier} derived from the file
* name.
*
* @param file Backing File
* @return A new YangTextSchemaSource
* @throws IllegalArgumentException if the file name has invalid format or if the supplied File is not a file
* @throws NullPointerException if file is null
*/
public static YangTextSchemaSource forFile(final File file) {
Preconditions.checkArgument(file.isFile(), "Supplied file %s is not a file");
return new YangTextFileSchemaSource(identifierFromFilename(file.getName()), file);
}
/**
* Create a new {@link YangTextSchemaSource} backed by a resource available in the ClassLoader where this
* class resides.
*
* @param resourceName Resource name
* @return A new instance.
* @throws IllegalArgumentException if the resource does not exist or if the name has invalid format
*/
public static ResourceYangTextSchemaSource forResource(final String resourceName) {
return forResource(YangTextSchemaSource.class, resourceName);
}
/**
* Create a new {@link YangTextSchemaSource} backed by a resource by a resource available on the ClassLoader
* which loaded the specified class.
*
* @param clazz Class reference
* @param resourceName Resource name
* @return A new instance.
* @throws IllegalArgumentException if the resource does not exist or if the name has invalid format
*/
public static ResourceYangTextSchemaSource forResource(final Class<?> clazz, final String resourceName) {
final String fileName = resourceName.substring(resourceName.lastIndexOf('/') + 1);
final SourceIdentifier identifier = identifierFromFilename(fileName);
final URL url = Resources.getResource(clazz, resourceName);
return new ResourceYangTextSchemaSource(identifier, url);
}
@Override
public final SourceIdentifier getIdentifier() {
return identifier;
}
@Nonnull
@Override
public Class<? extends YangTextSchemaSource> getType() {
return YangTextSchemaSource.class;
}
@Override
public final String toString() {
return addToStringAttributes(MoreObjects.toStringHelper(this).add("identifier", identifier)).toString();
}
/**
* Add subclass-specific attributes to the output {@link #toString()} output. Since
* subclasses are prevented from overriding {@link #toString()} for consistency
* reasons, they can add their specific attributes to the resulting string by attaching
* attributes to the supplied {@link ToStringHelper}.
*
* @param toStringHelper ToStringHelper onto the attributes can be added
* @return ToStringHelper supplied as input argument.
*/
protected abstract ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper);
}