BUG-4688: Make SourceIdentifier use Revision
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / TypeDefEffectiveStatementImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
9
10 import java.util.Collection;
11 import java.util.Map;
12 import javax.annotation.Nonnull;
13 import org.opendaylight.yangtools.yang.common.QName;
14 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
15 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
16 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
17 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
18 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
19 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
20 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
21 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
22 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
24 import org.opendaylight.yangtools.yang.model.util.type.DerivedTypeBuilder;
25 import org.opendaylight.yangtools.yang.model.util.type.DerivedTypes;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
27 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
28 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public final class TypeDefEffectiveStatementImpl extends AbstractEffectiveSchemaNode<TypedefStatement> implements
33         TypedefEffectiveStatement {
34     private static final Logger LOG = LoggerFactory.getLogger(TypeDefEffectiveStatementImpl.class);
35
36     private final TypeDefinition<?> typeDefinition;
37
38     private TypeEffectiveStatement<TypeStatement> typeStatement;
39
40     public TypeDefEffectiveStatementImpl(final StmtContext<QName, TypedefStatement, ?> ctx) {
41         super(ctx);
42
43         final TypeEffectiveStatement<?> typeEffectiveStmt = firstSubstatementOfType(TypeEffectiveStatement.class);
44         final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(typeEffectiveStmt.getTypeDefinition(),
45             ctx.getSchemaPath().get());
46         String defaultValue = null;
47         for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
48             if (stmt instanceof DefaultEffectiveStatementImpl) {
49                 defaultValue = ((DefaultEffectiveStatementImpl) stmt).argument();
50                 builder.setDefaultValue(defaultValue);
51             } else if (stmt instanceof DescriptionEffectiveStatementImpl) {
52                 builder.setDescription(((DescriptionEffectiveStatementImpl)stmt).argument());
53             } else if (stmt instanceof ReferenceEffectiveStatementImpl) {
54                 builder.setReference(((ReferenceEffectiveStatementImpl)stmt).argument());
55             } else if (stmt instanceof StatusEffectiveStatementImpl) {
56                 builder.setStatus(((StatusEffectiveStatementImpl)stmt).argument());
57             } else if (stmt instanceof UnitsEffectiveStatementImpl) {
58                 builder.setUnits(((UnitsEffectiveStatementImpl)stmt).argument());
59             } else if (stmt instanceof UnknownEffectiveStatementImpl) {
60                 // FIXME: should not directly implement, I think
61                 builder.addUnknownSchemaNode((UnknownEffectiveStatementImpl)stmt);
62             } else {
63                 if (!(stmt instanceof TypeEffectiveStatement)) {
64                     LOG.debug("Ignoring statement {}", stmt);
65                 }
66             }
67         }
68
69         SourceException.throwIf(
70                 TypeUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeEffectiveStmt, defaultValue),
71                 ctx.getStatementSourceReference(),
72                 "Typedef '%s' has default value '%s' marked with an if-feature statement.", ctx.getStatementArgument(),
73                 defaultValue);
74
75         typeDefinition = builder.build();
76     }
77
78     @Nonnull
79     @Override
80     public TypeDefinition<?> getTypeDefinition() {
81         return typeDefinition;
82     }
83
84     public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
85         TypeEffectiveStatement<TypeStatement> ret = typeStatement;
86         if (ret == null) {
87             synchronized (this) {
88                 ret = typeStatement;
89                 if (ret == null) {
90                     ret = new ProxyTypeEffectiveStatement();
91                     typeStatement = ret;
92                 }
93             }
94         }
95
96         return ret;
97     }
98
99     private final class ProxyTypeEffectiveStatement implements TypeEffectiveStatement<TypeStatement> {
100         @Override
101         public TypeStatement getDeclared() {
102             return null;
103         }
104
105         @Override
106         public <K, V, N extends IdentifierNamespace<K, V>> V get(@Nonnull final Class<N> namespace,
107                 @Nonnull final K identifier) {
108             return TypeDefEffectiveStatementImpl.this.get(namespace, identifier);
109         }
110
111         @Override
112         public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(@Nonnull final Class<N> namespace) {
113             return TypeDefEffectiveStatementImpl.this.getAll(namespace);
114         }
115
116         @Nonnull
117         @Override
118         public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
119             return TypeDefEffectiveStatementImpl.this.effectiveSubstatements();
120         }
121
122         @Nonnull
123         @Override
124         public StatementDefinition statementDefinition() {
125             return YangStmtMapping.TYPE;
126         }
127
128         @Override
129         public String argument() {
130             return getQName().getLocalName();
131         }
132
133         @Nonnull
134         @Override
135         public StatementSource getStatementSource() {
136             return StatementSource.CONTEXT;
137         }
138
139         @Nonnull
140         @Override
141         public TypeDefinition<?> getTypeDefinition() {
142             return TypeDefEffectiveStatementImpl.this.getTypeDefinition();
143         }
144     }
145 }