Clean up DefaultYangParser
[yangtools.git] / parser / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / DefaultYangParser.java
1 /*
2  * Copyright (c) 2021 PANTHEON.tech, 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 java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.ImmutableSet;
13 import com.google.common.collect.SetMultimap;
14 import java.io.IOException;
15 import java.util.List;
16 import javax.xml.transform.TransformerException;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
20 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
21 import org.opendaylight.yangtools.yang.model.api.stmt.FeatureSet;
22 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
23 import org.opendaylight.yangtools.yang.model.repo.api.YangIRSchemaSource;
24 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
25 import org.opendaylight.yangtools.yang.model.repo.api.YinDomSchemaSource;
26 import org.opendaylight.yangtools.yang.model.repo.api.YinTextSchemaSource;
27 import org.opendaylight.yangtools.yang.model.repo.api.YinXmlSchemaSource;
28 import org.opendaylight.yangtools.yang.parser.api.YangParser;
29 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
30 import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException;
31 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
32 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinStatementStreamSource;
33 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinTextToDomTransformer;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
35 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
36 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
37 import org.xml.sax.SAXException;
38
39 final class DefaultYangParser implements YangParser {
40     static final @NonNull ImmutableSet<Class<? extends SchemaSourceRepresentation>> REPRESENTATIONS = ImmutableSet.of(
41         // In order of preference
42         YangIRSchemaSource.class,
43         YangTextSchemaSource.class,
44         YinDomSchemaSource.class,
45         YinXmlSchemaSource.class,
46         YinTextSchemaSource.class);
47
48     private final BuildAction buildAction;
49
50     DefaultYangParser(final BuildAction buildAction) {
51         this.buildAction = requireNonNull(buildAction);
52     }
53
54     @Override
55     public ImmutableSet<Class<? extends SchemaSourceRepresentation>> supportedSourceRepresentations() {
56         return REPRESENTATIONS;
57     }
58
59     @Override
60     public YangParser addSource(final SchemaSourceRepresentation source) throws IOException, YangSyntaxErrorException {
61         buildAction.addSource(sourceToStatementStream(source));
62         return this;
63     }
64
65     @Override
66     public YangParser addLibSource(final SchemaSourceRepresentation source)
67             throws IOException, YangSyntaxErrorException {
68         buildAction.addLibSource(sourceToStatementStream(source));
69         return this;
70     }
71
72     @Override
73     public YangParser setSupportedFeatures(final FeatureSet supportedFeatures) {
74         buildAction.setSupportedFeatures(supportedFeatures);
75         return this;
76     }
77
78     @Override
79     public YangParser setModulesWithSupportedDeviations(
80             final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
81         buildAction.setModulesWithSupportedDeviations(modulesDeviatedByModules);
82         return this;
83     }
84
85     @Override
86     public List<DeclaredStatement<?>> buildDeclaredModel() throws YangParserException {
87         try {
88             return buildAction.build().getRootStatements();
89         } catch (ReactorException e) {
90             throw decodeReactorException(e);
91         }
92     }
93
94     @Override
95     public EffectiveModelContext buildEffectiveModel() throws YangParserException {
96         try {
97             return buildAction.buildEffective();
98         } catch (ReactorException e) {
99             throw decodeReactorException(e);
100         }
101     }
102
103     static YangParserException decodeReactorException(final ReactorException reported) {
104         // FIXME: map exception in some reasonable manner
105         return new YangParserException("Failed to assemble sources", reported);
106     }
107
108     static StatementStreamSource sourceToStatementStream(final SchemaSourceRepresentation source)
109             throws IOException, YangSyntaxErrorException {
110         requireNonNull(source);
111         if (source instanceof YangIRSchemaSource irSource) {
112             return YangStatementStreamSource.create(irSource);
113         } else if (source instanceof YangTextSchemaSource yangSource) {
114             return YangStatementStreamSource.create(yangSource);
115         } else if (source instanceof YinDomSchemaSource yinDom) {
116             return YinStatementStreamSource.create(yinDom);
117         } else if (source instanceof YinTextSchemaSource yinText) {
118             try {
119                 return YinStatementStreamSource.create(YinTextToDomTransformer.transformSource(yinText));
120             } catch (SAXException e) {
121                 throw new YangSyntaxErrorException(source.getIdentifier(), 0, 0, "Failed to parse XML text", e);
122             }
123         } else if (source instanceof YinXmlSchemaSource yinXml) {
124             try {
125                 return YinStatementStreamSource.create(yinXml);
126             } catch (TransformerException e) {
127                 throw new YangSyntaxErrorException(source.getIdentifier(), 0, 0,
128                     "Failed to assemble in-memory representation", e);
129             }
130         } else {
131             throw new IllegalArgumentException("Unsupported source " + source);
132         }
133     }
134 }