BUG-6522: share instances of Config(Effective)Statement
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / TypeDefEffectiveStatementImpl.java
index fe9e1389c70f88b58abed5acfddce84866e01e02..576441fa53d06ef7bd712ac51b1392a5e5afe87d 100644 (file)
  */
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
 
-import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
-
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.Decimal64SpecificationEffectiveStatementImpl;
-import java.util.ArrayList;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.LengthEffectiveStatementImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.PatternEffectiveStatementImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.RangeEffectiveStatementImpl;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import java.util.Collections;
-import java.util.List;
+import java.util.Collection;
+import java.util.Map;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 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.api.type.LengthConstraint;
-import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
-import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
-import org.opendaylight.yangtools.yang.model.util.ExtendedType;
-import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
-import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
+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.stmt.rfc6020.TypeUtils;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.TypeDefinitionEffectiveBuilder;
-
-public class TypeDefEffectiveStatementImpl extends
-        EffectiveStatementBase<QName, TypedefStatement> implements
-        TypeDefinition<TypeDefinition<?>>, TypeDefinitionEffectiveBuilder {
-
-    private final QName qName;
-    private final SchemaPath path;
-
-    private final TypeDefinition<?> baseType;
-
-    private String defaultValue;
-    private String units;
-
-    private String description;
-    private String reference;
-
-    private Status status;
-
-    private final List<RangeConstraint> ranges;
-    private final List<LengthConstraint> lengths;
-    private final List<PatternConstraint> patterns;
-    private final Integer fractionDigits;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-    private ExtendedType extendedType = null;
+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(
-            StmtContext<QName, TypedefStatement, ?> ctx) {
+    public TypeDefEffectiveStatementImpl(final StmtContext<QName, TypedefStatement, ?> ctx) {
         super(ctx);
 
-        qName = ctx.getStatementArgument();
-        path = Utils.getSchemaPath(ctx);
-        baseType = parseBaseTypeFromCtx(ctx);
-
-        EffectiveStatementBase<?, ?> typeEffectiveStmt = firstSubstatementOfType(
-                TypeDefinition.class, EffectiveStatementBase.class);
-
-        ranges = initRanges(typeEffectiveStmt);
-        lengths = initLengths(typeEffectiveStmt);
-        patterns = initPatterns(typeEffectiveStmt);
-
-        //due to compatibility problems with original yang parser
-        //:FIXME try to find out better solution
-        if (typeEffectiveStmt.argument().equals(TypeUtils.DECIMAL64)
-                && ranges.isEmpty()) {
-            fractionDigits = null;
-        } else {
-            fractionDigits = initFractionDigits(typeEffectiveStmt);
-        }
-
-        for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
-            if (effectiveStatement instanceof DefaultEffectiveStatementImpl) {
-                defaultValue = ((DefaultEffectiveStatementImpl) effectiveStatement)
-                        .argument();
-            }
-            if (effectiveStatement instanceof UnitsEffectiveStatementImpl) {
-                units = ((UnitsEffectiveStatementImpl) effectiveStatement)
-                        .argument();
-            }
-            if (effectiveStatement instanceof DescriptionEffectiveStatementImpl) {
-                description = ((DescriptionEffectiveStatementImpl) effectiveStatement)
-                        .argument();
-            }
-            if (effectiveStatement instanceof ReferenceEffectiveStatementImpl) {
-                reference = ((ReferenceEffectiveStatementImpl) effectiveStatement)
-                        .argument();
-            }
-            if (effectiveStatement instanceof StatusEffectiveStatementImpl) {
-                status = ((StatusEffectiveStatementImpl) effectiveStatement)
-                        .argument();
-            }
-        }
-    }
-
-    private TypeDefinition<?> parseBaseTypeFromCtx(
-            final StmtContext<QName, TypedefStatement, ?> ctx) {
-
-        TypeDefinition<?> baseType;
-
-        QName baseTypeQName = Utils.qNameFromArgument(ctx, StmtContextUtils
-                .firstAttributeOf(ctx.declaredSubstatements(),
-                        TypeStatement.class));
-
-        if (TypeUtils.isYangBuiltInTypeString(baseTypeQName.getLocalName())) {
-            baseType = TypeUtils.getYangPrimitiveTypeFromString(baseTypeQName
-                    .getLocalName());
-            if (baseType == null) {
-                baseType = firstSubstatementOfType(TypeDefinition.class);
-
-                //due to compatibility problems with original yang parser
-                //:FIXME try to find out better solution
-                if(baseType instanceof Decimal64SpecificationEffectiveStatementImpl) {
-                    Decimal64SpecificationEffectiveStatementImpl decimal64 = (Decimal64SpecificationEffectiveStatementImpl) baseType;
-                    if(decimal64.isExtended()) {
-                        baseType = decimal64.getBaseType();
-                    }
+        final TypeEffectiveStatement<?> typeEffectiveStmt = firstSubstatementOfType(TypeEffectiveStatement.class);
+        final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(typeEffectiveStmt.getTypeDefinition(),
+            ctx.getSchemaPath().get());
+        for (EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
+            if (stmt instanceof DefaultEffectiveStatementImpl) {
+                builder.setDefaultValue(stmt.argument());
+            } 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);
                 }
             }
-        } else {
-            StmtContext<?, TypedefStatement, EffectiveStatement<QName, TypedefStatement>> baseTypeCtx = ctx
-                    .getParentContext().getFromNamespace(TypeNamespace.class,
-                            baseTypeQName);
-            baseType = (TypeDefEffectiveStatementImpl) baseTypeCtx
-                    .buildEffective();
         }
 
-        return baseType;
+        typeDefinition = builder.build();
     }
 
-    protected Integer initFractionDigits(
-            EffectiveStatementBase<?, ?> typeEffectiveStmt) {
-        final FractionDigitsEffectiveStatementImpl fractionDigitsEffStmt = typeEffectiveStmt
-                .firstEffective(FractionDigitsEffectiveStatementImpl.class);
-        return fractionDigitsEffStmt != null ? fractionDigitsEffStmt.argument()
-                : null;
-    }
-
-    protected List<RangeConstraint> initRanges(
-            EffectiveStatementBase<?, ?> typeEffectiveStmt) {
-        final RangeEffectiveStatementImpl rangeConstraints = typeEffectiveStmt
-                .firstEffective(RangeEffectiveStatementImpl.class);
-        return rangeConstraints != null ? rangeConstraints.argument()
-                : Collections.<RangeConstraint> emptyList();
-    }
-
-    protected List<LengthConstraint> initLengths(
-            EffectiveStatementBase<?, ?> typeEffectiveStmt) {
-        final LengthEffectiveStatementImpl lengthConstraints = typeEffectiveStmt
-                .firstEffective(LengthEffectiveStatementImpl.class);
-        return lengthConstraints != null ? lengthConstraints.argument()
-                : Collections.<LengthConstraint> emptyList();
-    }
-
-    protected List<PatternConstraint> initPatterns(
-            EffectiveStatementBase<?, ?> typeEffectiveStmt) {
-        final List<PatternConstraint> patternConstraints = new ArrayList<>();
-
-        for (final EffectiveStatement<?, ?> effectiveStatement : typeEffectiveStmt
-                .effectiveSubstatements()) {
-            if (effectiveStatement instanceof PatternEffectiveStatementImpl) {
-                final PatternConstraint pattern = ((PatternEffectiveStatementImpl) effectiveStatement)
-                        .argument();
-
-                if (pattern != null) {
-                    patternConstraints.add(pattern);
+    @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 !patternConstraints.isEmpty() ? ImmutableList
-                .copyOf(patternConstraints) : Collections
-                .<PatternConstraint> emptyList();
-    }
-
-    @Override
-    public TypeDefinition<?> getBaseType() {
-        return baseType;
+        return ret;
     }
 
-    @Override
-    public String getUnits() {
-        return units;
-    }
-
-    @Override
-    public Object getDefaultValue() {
-        return defaultValue;
-    }
-
-    @Override
-    public QName getQName() {
-        return qName;
-    }
-
-    @Override
-    public SchemaPath getPath() {
-        return path;
-    }
-
-    @Override
-    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
-    public String getReference() {
-        return reference;
-    }
-
-    @Override
-    public Status getStatus() {
-        return status;
-    }
-
-    public List<RangeConstraint> getRangeConstraints() {
-        return ranges;
-    }
-
-    public List<LengthConstraint> getLengthConstraints() {
-        return lengths;
-    }
-
-    public List<PatternConstraint> getPatternConstraints() {
-        return patterns;
-    }
-
-    public Integer getFractionDigits() {
-        return fractionDigits;
-    }
+    private final class ProxyTypeEffectiveStatement implements TypeEffectiveStatement<TypeStatement> {
+        @Override
+        public TypeStatement getDeclared() {
+            return null;
+        }
 
-    @Override
-    public ExtendedType buildType() {
+        @Override
+        public <K, V, N extends IdentifierNamespace<K, V>> V get(final Class<N> namespace, final K identifier) {
+            return TypeDefEffectiveStatementImpl.this.get(namespace, identifier);
+        }
 
-        if (extendedType != null) {
-            return extendedType;
+        @Override
+        public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(final Class<N> namespace) {
+            return TypeDefEffectiveStatementImpl.this.getAll(namespace);
         }
 
-        Builder extendedTypeBuilder;
-        if (baseType instanceof TypeDefinitionEffectiveBuilder) {
-            TypeDefinitionEffectiveBuilder typeDefBaseType = (TypeDefinitionEffectiveBuilder) baseType;
-            extendedTypeBuilder = ExtendedType.builder(qName,
-                    typeDefBaseType.buildType(),
-                    Optional.fromNullable(description),
-                    Optional.fromNullable(reference), path);
-        } else {
-            extendedTypeBuilder = ExtendedType.builder(qName, baseType,
-                    Optional.fromNullable(description),
-                    Optional.fromNullable(reference), path);
+        @Override
+        public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+            // FIXME: this is tricky
+            throw new UnsupportedOperationException("Not implemented yet");
         }
 
-        extendedTypeBuilder.defaultValue(defaultValue);
-        extendedTypeBuilder.units(units);
+        @Override
+        public StatementDefinition statementDefinition() {
+            return Rfc6020Mapping.TYPE;
+        }
 
-        extendedTypeBuilder.fractionDigits(fractionDigits);
-        extendedTypeBuilder.ranges(ranges);
-        extendedTypeBuilder.lengths(lengths);
-        extendedTypeBuilder.patterns(patterns);
+        @Override
+        public String argument() {
+            return getQName().getLocalName();
+        }
 
-        extendedType = extendedTypeBuilder.build();
+        @Override
+        public StatementSource getStatementSource() {
+            return StatementSource.CONTEXT;
+        }
 
-        return extendedType;
+        @Override
+        public TypeDefinition<?> getTypeDefinition() {
+            return TypeDefEffectiveStatementImpl.this.getTypeDefinition();
+        }
     }
 }