Optimize simple declared statements
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / AbstractDeclaredStatement.java
1 /*
2  * Copyright (c) 2020 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.rfc7950.stmt;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.collect.ImmutableList;
12 import java.util.Collection;
13 import org.eclipse.jdt.annotation.NonNull;
14 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
15 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
16 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
17
18 /**
19  * An abstract base class for {@link DeclaredStatement} implementations. This is a direct competition to
20  * {@link org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement}, providing lower-footprint
21  * implementations.
22  */
23 @Beta
24 public abstract class AbstractDeclaredStatement<A> implements DeclaredStatement<A> {
25     protected AbstractDeclaredStatement() {
26     }
27
28     @Override
29     public final StatementSource getStatementSource() {
30         return StatementSource.DECLARATION;
31     }
32
33     @Override
34     public Collection<? extends DeclaredStatement<?>> declaredSubstatements() {
35         // Default to reduce load on subclasses and keep the number of implementations down
36         return ImmutableList.of();
37     }
38
39     /**
40      * Utility method for squashing singleton lists into single objects. This is a CPU/mem trade-off, which we are
41      * usually willing to make: for the cost of an instanceof check we can save one object and re-create it when needed.
42      * The inverse operation is #unmaskSubstatements(Object)}.
43      *
44      * @param substatements substatements to mask
45      * @return Masked substatements
46      * @throws NullPointerException if substatements is null
47      */
48     protected static final @NonNull Object maskSubstatements(
49             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
50         // Note: ImmutableList guarantees non-null content
51         return substatements.size() == 1 ? substatements.get(0) : substatements;
52     }
53
54     /**
55      * Utility method for recovering singleton lists squashed by {@link #maskSubstatements(ImmutableList)}.
56      *
57      * @param masked substatements to unmask
58      * @return List of substatements
59      * @throws NullPointerException if masked is null
60      * @throws ClassCastException if masked object was not produced by {@link #maskSubstatements(ImmutableList)}
61      */
62     @SuppressWarnings("unchecked")
63     protected static final @NonNull ImmutableList<? extends DeclaredStatement<?>> unmaskSubstatements(
64             final @NonNull Object masked) {
65         return masked instanceof ImmutableList ? (ImmutableList<? extends DeclaredStatement<?>>) masked
66                 // Yes, this is ugly code, which could use an explicit verify, that would just change the what sort
67                 // of exception we throw. ClassCastException is as good as VerifyException.
68                 : ImmutableList.of((DeclaredStatement<?>) masked);
69     }
70
71     public abstract static class WithRawArgument<A> extends AbstractDeclaredStatement<A> {
72         private final String rawArgument;
73
74         protected WithRawArgument(final StmtContext<A, ?, ?> context) {
75             rawArgument = context.rawStatementArgument();
76         }
77
78         @Override
79         public final String rawArgument() {
80             return rawArgument;
81         }
82     }
83
84     public abstract static class WithRawStringArgument extends WithRawArgument<String> {
85         protected WithRawStringArgument(final StmtContext<String, ?, ?> context) {
86             super(context);
87         }
88
89         @Override
90         public final String argument() {
91             return rawArgument();
92         }
93     }
94
95     public abstract static class WithArgument<A> extends WithRawArgument<A> {
96         private final A argument;
97
98         protected WithArgument(final StmtContext<A, ?, ?> context) {
99             super(context);
100             argument = context.getStatementArgument();
101         }
102
103         @Override
104         public final A argument() {
105             return argument;
106         }
107     }
108 }