/*
* Copyright (c) 2015 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.parser.stmt.rfc6020.effective;
import java.util.Collection;
import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
import org.opendaylight.yangtools.yang.model.util.type.DerivedTypeBuilder;
import org.opendaylight.yangtools.yang.model.util.type.DerivedTypes;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class TypeDefEffectiveStatementImpl extends AbstractEffectiveSchemaNode<TypedefStatement> implements
TypedefEffectiveStatement {
private static final Logger LOG = LoggerFactory.getLogger(TypeDefEffectiveStatementImpl.class);
private final TypeDefinition<?> typeDefinition;
private TypeEffectiveStatement<TypeStatement> typeStatement;
public TypeDefEffectiveStatementImpl(final StmtContext<QName, TypedefStatement, ?> ctx) {
super(ctx);
final TypeEffectiveStatement<?> typeEffectiveStmt = firstSubstatementOfType(TypeEffectiveStatement.class);
final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(typeEffectiveStmt.getTypeDefinition(),
ctx.getSchemaPath().get());
String defaultValue = null;
for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
if (stmt instanceof DefaultEffectiveStatementImpl) {
defaultValue = ((DefaultEffectiveStatementImpl) stmt).argument();
builder.setDefaultValue(defaultValue);
} else if (stmt instanceof DescriptionEffectiveStatementImpl) {
builder.setDescription(((DescriptionEffectiveStatementImpl)stmt).argument());
} else if (stmt instanceof ReferenceEffectiveStatementImpl) {
builder.setReference(((ReferenceEffectiveStatementImpl)stmt).argument());
} else if (stmt instanceof StatusEffectiveStatementImpl) {
builder.setStatus(((StatusEffectiveStatementImpl)stmt).argument());
} else if (stmt instanceof UnitsEffectiveStatementImpl) {
builder.setUnits(((UnitsEffectiveStatementImpl)stmt).argument());
} else if (stmt instanceof UnknownEffectiveStatementImpl) {
// FIXME: should not directly implement, I think
builder.addUnknownSchemaNode((UnknownEffectiveStatementImpl)stmt);
} else {
if (!(stmt instanceof TypeEffectiveStatement)) {
LOG.debug("Ignoring statement {}", stmt);
}
}
}
try {
SourceException
.throwIf(TypeUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeEffectiveStmt,
defaultValue), ctx.getStatementSourceReference(),
"Typedef '%s' has default value '%s' marked with an if-feature statement.", ctx
.getStatementArgument(), defaultValue);
} catch (final IllegalStateException e) {
throw new SourceException(ctx.getStatementSourceReference(), e,
"Unable to find a default value for typedef '%s'", ctx.getStatementArgument());
}
typeDefinition = builder.build();
}
@Nonnull
@Override
public TypeDefinition<?> getTypeDefinition() {
return typeDefinition;
}
public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
TypeEffectiveStatement<TypeStatement> ret = typeStatement;
if (ret == null) {
synchronized (this) {
ret = typeStatement;
if (ret == null) {
ret = new ProxyTypeEffectiveStatement();
typeStatement = ret;
}
}
}
return ret;
}
private final class ProxyTypeEffectiveStatement implements TypeEffectiveStatement<TypeStatement> {
@Override
public TypeStatement getDeclared() {
return null;
}
@Override
public <K, V, N extends IdentifierNamespace<K, V>> V get(@Nonnull final Class<N> namespace, @Nonnull final K identifier) {
return TypeDefEffectiveStatementImpl.this.get(namespace, identifier);
}
@Override
public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(@Nonnull final Class<N> namespace) {
return TypeDefEffectiveStatementImpl.this.getAll(namespace);
}
@Nonnull
@Override
public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
return TypeDefEffectiveStatementImpl.this.effectiveSubstatements();
}
@Nonnull
@Override
public StatementDefinition statementDefinition() {
return YangStmtMapping.TYPE;
}
@Override
public String argument() {
return getQName().getLocalName();
}
@Nonnull
@Override
public StatementSource getStatementSource() {
return StatementSource.CONTEXT;
}
@Nonnull
@Override
public TypeDefinition<?> getTypeDefinition() {
return TypeDefEffectiveStatementImpl.this.getTypeDefinition();
}
}
}