/* Copyright (c) 2011 Danish Maritime Authority. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.maritimecloud.internal.msdl.parser; import static java.util.Objects.requireNonNull; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import net.maritimecloud.internal.msdl.parser.antlr.AntlrFile; import net.maritimecloud.internal.msdl.parser.antlr.generated.MsdlParser.BroadcastDeclarationContext; import net.maritimecloud.internal.msdl.parser.antlr.generated.MsdlParser.EndpointDeclarationContext; import net.maritimecloud.internal.msdl.parser.antlr.generated.MsdlParser.EnumDeclarationContext; import net.maritimecloud.internal.msdl.parser.antlr.generated.MsdlParser.ImportDeclarationContext; import net.maritimecloud.internal.msdl.parser.antlr.generated.MsdlParser.MessageDeclarationContext; import net.maritimecloud.internal.msdl.parser.antlr.generated.MsdlParser.NamespaceDeclarationContext; import net.maritimecloud.internal.msdl.parser.antlr.generated.MsdlParser.TypeDeclarationContext; import net.maritimecloud.msdl.model.BroadcastMessageDeclaration; import net.maritimecloud.msdl.model.EndpointDefinition; import net.maritimecloud.msdl.model.EnumDeclaration; import net.maritimecloud.msdl.model.MessageDeclaration; import net.maritimecloud.msdl.model.MsdlFile; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ParseTree; /** * * @author Kasper Nielsen */ class ParsedMsdlFile implements MsdlFile { final AntlrFile antlrFile; final List<AbstractContainer> containers = new ArrayList<>(); final ArrayList<Import> imports = new ArrayList<>(); String namespace; final ParsedProject project; final ArrayList<ParsedMsdlFile> resolvedImports = new ArrayList<>(); ParsedMsdlFile(ParsedProject project, AntlrFile antlrFile) { this.antlrFile = requireNonNull(antlrFile); this.project = requireNonNull(project); } String prefix(ParserRuleContext context) { return antlrFile.getPath() + ":[" + context.getStart().getLine() + ":" + context.getStart().getCharPositionInLine() + "] "; } void error(ParserRuleContext context, String msg) { project.logger.error(prefix(context) + msg); } void warn(ParserRuleContext context, String msg) { project.logger.warn(prefix(context) + msg); } /** * @return the broadcasts */ public List<BroadcastMessageDeclaration> getBroadcasts() { return listOf(BroadcastMessageDeclaration.class); } /** * @return the endpoints */ public List<EndpointDefinition> getEndpoints() { return listOf(EndpointDefinition.class); } /** {@inheritDoc} */ @Override public List<EnumDeclaration> getEnums() { return listOf(EnumDeclaration.class); } /** {@inheritDoc} */ @Override public List<MessageDeclaration> getMessages() { List<MessageDeclaration> msgs = listOf(MessageDeclaration.class); return msgs.stream().filter(e -> !(e instanceof BroadcastMessageDeclaration)).collect(Collectors.toList()); } /** {@inheritDoc} */ @Override public String getName() { String filename = antlrFile.getPath().getFileName().toString(); return filename.substring(0, filename.length() - 5); } /** {@inheritDoc} */ @Override public String getNamespace() { return namespace; } @SuppressWarnings("unchecked") <T> List<T> listOf(Class<T> type) { ArrayList<T> result = new ArrayList<>(); for (Object o : containers) { if (type.isAssignableFrom(o.getClass())) { result.add((T) o); } } return result; } void parse() { parseNamespace(); parseImports(); parseTypes(); } private void parseImports() { for (ImportDeclarationContext importContext : antlrFile.getCompilationUnit().importDeclaration()) { if (importContext.getChild(1) != null) { imports.add(new Import(importContext)); } } } private void parseNamespace() { NamespaceDeclarationContext namespaceContext = antlrFile.getCompilationUnit().namespaceDeclaration(); // namespace is optional if (namespaceContext != null) { namespace = namespaceContext.getChild(1).getText(); // TODO validate name spaces } else { // project.logger.error(antlrFile.getPath() + ": A MSDL file must have a valid namespace"); } } private void parseTypes() { for (TypeDeclarationContext tdc : antlrFile.getCompilationUnit().typeDeclaration()) { AnnotationContainer ac = new AnnotationContainer(this).parse(tdc); ParseTree child = tdc.getChild(tdc.getChildCount() - 1); if (child instanceof EnumDeclarationContext) { containers.add(new ParsedEnum(this, ac).parse((EnumDeclarationContext) child)); } else if (child instanceof MessageDeclarationContext) { containers.add(new ParsedMessage(this, ac).parse((MessageDeclarationContext) child)); } else if (child instanceof BroadcastDeclarationContext) { containers.add(new ParsedBroadcastMessage(this, ac).parse((BroadcastDeclarationContext) child)); } else if (child instanceof EndpointDeclarationContext) { containers.add(new ParsedEndpoint(this, ac).parse((EndpointDeclarationContext) child)); } } } public String toString() { return antlrFile.getPath().toString(); } static class Import { final ImportDeclarationContext importContext; Import(ImportDeclarationContext importContext) { this.importContext = requireNonNull(importContext); } public String getName() { String p = importContext.getChild(1).getText(); return p.substring(1, p.length() - 1); } } }