Bug 4410: Loop in typedefs causes stack overflow
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / TypeStatementImpl.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;
9
10 import java.util.Collection;
11 import javax.annotation.Nonnull;
12 import org.opendaylight.yangtools.yang.common.QName;
13 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
14 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
15 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
16 import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
17 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
18 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
19 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
26 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
27 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
28 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ExtendedTypeEffectiveStatementImpl;
29 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.BinaryEffectiveStatementImpl;
30 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.BooleanEffectiveStatementImpl;
31 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.EmptyEffectiveStatementImpl;
32 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.Int16EffectiveStatementImpl;
33 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.Int32EffectiveStatementImpl;
34 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.Int64EffectiveStatementImpl;
35 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.Int8EffectiveStatementImpl;
36 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.StringEffectiveStatementImpl;
37 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.UInt16EffectiveStatementImpl;
38 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.UInt32EffectiveStatementImpl;
39 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.UInt64EffectiveStatementImpl;
40 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.UInt8EffectiveStatementImpl;
41
42 public class TypeStatementImpl extends AbstractDeclaredStatement<String>
43         implements TypeStatement {
44
45     protected TypeStatementImpl(final StmtContext<String, TypeStatement, ?> context) {
46         super(context);
47     }
48
49     public static class Definition
50             extends
51             AbstractStatementSupport<String, TypeStatement, EffectiveStatement<String, TypeStatement>> {
52
53         public Definition() {
54             super(Rfc6020Mapping.TYPE);
55         }
56
57         @Override
58         public String parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value)
59                 throws SourceException {
60             return value;
61         }
62
63         @Override
64         public TypeStatement createDeclared(
65                 final StmtContext<String, TypeStatement, ?> ctx) {
66             return new TypeStatementImpl(ctx);
67         }
68
69         @Override
70         public EffectiveStatement<String, TypeStatement> createEffective(
71                 final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx) {
72
73             // :FIXME improve the test of isExtended - e.g. unknown statements,
74             // etc..
75             Collection<StatementContextBase<?, ?, ?>> declaredSubstatements = ctx
76                     .declaredSubstatements();
77             boolean isExtended = !declaredSubstatements.isEmpty();
78             if (isExtended) {
79                 return new ExtendedTypeEffectiveStatementImpl(ctx, true);
80             }
81
82             switch (ctx.getStatementArgument()) {
83             case TypeUtils.INT8:
84                 return new Int8EffectiveStatementImpl(ctx);
85             case TypeUtils.INT16:
86                 return new Int16EffectiveStatementImpl(ctx);
87             case TypeUtils.INT32:
88                 return new Int32EffectiveStatementImpl(ctx);
89             case TypeUtils.INT64:
90                 return new Int64EffectiveStatementImpl(ctx);
91             case TypeUtils.UINT8:
92                 return new UInt8EffectiveStatementImpl(ctx);
93             case TypeUtils.UINT16:
94                 return new UInt16EffectiveStatementImpl(ctx);
95             case TypeUtils.UINT32:
96                 return new UInt32EffectiveStatementImpl(ctx);
97             case TypeUtils.UINT64:
98                 return new UInt64EffectiveStatementImpl(ctx);
99             case TypeUtils.STRING:
100                 return new StringEffectiveStatementImpl(ctx);
101             case TypeUtils.BOOLEAN:
102                 return new BooleanEffectiveStatementImpl(ctx);
103             case TypeUtils.EMPTY:
104                 return new EmptyEffectiveStatementImpl(ctx);
105             case TypeUtils.BINARY:
106                 return new BinaryEffectiveStatementImpl(ctx);
107             default:
108                 // :FIXME try to resolve original typedef context here and
109                 // return buildEffective of original typedef context
110                 return new ExtendedTypeEffectiveStatementImpl(ctx, false);
111             }
112         }
113
114         @Override
115         public void onFullDefinitionDeclared(
116                 final Mutable<String, TypeStatement, EffectiveStatement<String, TypeStatement>> stmt)
117                 throws SourceException {
118
119             // if it is yang built-in type, no prerequisite is needed, so simply return
120             if (TypeUtils.isYangBuiltInTypeString(stmt.getStatementArgument())) {
121                 return;
122             }
123
124             final QName typeQName = Utils.qNameFromArgument(stmt, stmt.getStatementArgument());
125             final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
126             final Prerequisite<StmtContext<?, ?, ?>> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class,
127                     typeQName, ModelProcessingPhase.EFFECTIVE_MODEL);
128             typeAction.mutatesEffectiveCtx(stmt.getParentContext());
129
130             /*
131              * If the type does not exist, throw new InferenceException.
132              * Otherwise perform no operation.
133              */
134             typeAction.apply(new InferenceAction() {
135
136                 @Override
137                 public void apply() {
138                     // Intentional NOOP
139                 }
140
141                 @Override
142                 public void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed) {
143                     if (failed.contains(typePrereq)) {
144                         throw new InferenceException(String.format("Type [%s] was not found.", typeQName), stmt
145                                 .getStatementSourceReference());
146                     }
147                 }
148             });
149         }
150     }
151
152     @Nonnull
153     @Override
154     public String getName() {
155         return argument();
156     }
157 }