Fix YangParserImpl streaming use
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / YangParserImpl.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies, s.r.o. 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.impl;
9
10 import static com.google.common.collect.ImmutableMap.toImmutableMap;
11 import static java.util.Objects.requireNonNull;
12 import static java.util.function.Function.identity;
13
14 import com.google.common.collect.ImmutableList;
15 import com.google.common.collect.SetMultimap;
16 import java.io.IOException;
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Set;
21 import javax.xml.transform.TransformerException;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.QNameModule;
24 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
25 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
26 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
29 import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
30 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
31 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
32 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
33 import org.opendaylight.yangtools.yang.model.repo.api.YinDomSchemaSource;
34 import org.opendaylight.yangtools.yang.model.repo.api.YinTextSchemaSource;
35 import org.opendaylight.yangtools.yang.model.repo.api.YinXmlSchemaSource;
36 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
37 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
38 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinStatementStreamSource;
39 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinTextToDomTransformer;
40 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
41 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
42 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
43 import org.xml.sax.SAXException;
44
45 final class YangParserImpl implements YangParser {
46     private static final Collection<Class<? extends SchemaSourceRepresentation>> REPRESENTATIONS = ImmutableList.of(
47         ASTSchemaSource.class, YangTextSchemaSource.class, YinDomSchemaSource.class, YinXmlSchemaSource.class,
48         YinTextSchemaSource.class);
49
50     private final BuildAction buildAction;
51
52     YangParserImpl(final BuildAction buildAction) {
53         this.buildAction = requireNonNull(buildAction);
54     }
55
56     @Override
57     public Collection<Class<? extends SchemaSourceRepresentation>> supportedSourceRepresentations() {
58         return REPRESENTATIONS;
59     }
60
61     @Override
62     public Set<QName> supportedStatements() {
63         // TODO Auto-generated method stub
64         return null;
65     }
66
67     @Override
68     public YangParser addSource(final SchemaSourceRepresentation source) throws IOException, YangSyntaxErrorException {
69         buildAction.addSources(sourceToStatementStream(source));
70         return this;
71     }
72
73     @Override
74     public YangParser addLibSource(final SchemaSourceRepresentation source) throws IOException,
75             YangSyntaxErrorException {
76         buildAction.addLibSources(sourceToStatementStream(source));
77         return this;
78     }
79
80     @Override
81     public YangParser setSupportedFeatures(final Set<QName> supportedFeatures) {
82         buildAction.setSupportedFeatures(supportedFeatures);
83         return this;
84     }
85
86     @Override
87     public YangParser setModulesWithSupportedDeviations(
88             final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
89         buildAction.setModulesWithSupportedDeviations(modulesDeviatedByModules);
90         return this;
91     }
92
93     @Override
94     public List<DeclaredStatement<?>> buildDeclaredModel() throws YangParserException {
95         try {
96             return buildAction.build().getRootStatements();
97         } catch (ReactorException e) {
98             throw decodeReactorException(e);
99         }
100     }
101
102     @Override
103     public Map<QNameModule, ModuleEffectiveStatement> buildEffectiveModel() throws YangParserException {
104         final List<EffectiveStatement<?, ?>> effectiveStatements;
105         try {
106             effectiveStatements = buildAction.buildEffective().getRootEffectiveStatements();
107         } catch (ReactorException e) {
108             throw decodeReactorException(e);
109         }
110
111         return effectiveStatements.stream()
112                 .filter(ModuleEffectiveStatement.class::isInstance).map(ModuleEffectiveStatement.class::cast)
113                 .collect(toImmutableMap(ModuleEffectiveStatement::localQNameModule, identity()));
114     }
115
116     @Override
117     public SchemaContext buildSchemaContext() throws YangParserException {
118         try {
119             return buildAction.buildEffective();
120         } catch (ReactorException e) {
121             throw decodeReactorException(e);
122         }
123     }
124
125     private static YangParserException decodeReactorException(final ReactorException reported) {
126         // FIXME: map exception in some reasonable manner
127         return new YangParserException("Failed to assemble sources", reported);
128     }
129
130     private static StatementStreamSource sourceToStatementStream(final SchemaSourceRepresentation source)
131             throws IOException, YangSyntaxErrorException {
132         requireNonNull(source);
133         if (source instanceof ASTSchemaSource) {
134             return YangStatementStreamSource.create((ASTSchemaSource) source);
135         } else if (source instanceof YangTextSchemaSource) {
136             return YangStatementStreamSource.create((YangTextSchemaSource) source);
137         } else if (source instanceof YinDomSchemaSource) {
138             return YinStatementStreamSource.create((YinDomSchemaSource) source);
139         } else if (source instanceof YinTextSchemaSource) {
140             try {
141                 return YinStatementStreamSource.create(YinTextToDomTransformer.transformSource(
142                     (YinTextSchemaSource) source));
143             } catch (SAXException e) {
144                 throw new YangSyntaxErrorException(source.getIdentifier(), 0, 0, "Failed to parse XML text", e);
145             }
146         } else if (source instanceof YinXmlSchemaSource) {
147             try {
148                 return YinStatementStreamSource.create((YinXmlSchemaSource) source);
149             } catch (TransformerException e) {
150                 throw new YangSyntaxErrorException(source.getIdentifier(), 0, 0,
151                     "Failed to assemble in-memory representation", e);
152             }
153         } else {
154             throw new IllegalArgumentException("Unsupported source " + source);
155         }
156     }
157 }