2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.spi.meta;
10 import static com.google.common.base.Verify.verify;
11 import static java.util.Objects.requireNonNull;
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import org.eclipse.jdt.annotation.NonNullByDefault;
15 import org.eclipse.jdt.annotation.Nullable;
17 // FIXME: YANGTOOLS-1150: this should go into yang-reactor-api
19 public enum ModelProcessingPhase {
23 * Preliminary cross-source relationship resolution phase which collects available module names and module
24 * namespaces. It is necessary in order to correct resolution of unknown statements used in linkage phase (e.g.
25 * semantic version of YANG modules).
27 SOURCE_PRE_LINKAGE(INIT, ExecutionOrder.SOURCE_PRE_LINKAGE),
30 * Cross-source relationship resolution phase.
33 * In this phase of processing only statements which affects cross-source relationship (e.g. imports / includes)
37 * At end of this phase all source related contexts should be bind to their imports and includes to allow
38 * visibility of custom defined statements in subsequent phases.
40 SOURCE_LINKAGE(SOURCE_PRE_LINKAGE, ExecutionOrder.SOURCE_LINKAGE),
41 STATEMENT_DEFINITION(SOURCE_LINKAGE, ExecutionOrder.STATEMENT_DEFINITION),
42 FULL_DECLARATION(STATEMENT_DEFINITION, ExecutionOrder.FULL_DECLARATION),
43 EFFECTIVE_MODEL(FULL_DECLARATION, ExecutionOrder.EFFECTIVE_MODEL);
46 * The concept of phase execution order, expressed as non-negative values.
48 public static final class ExecutionOrder {
50 * Equivalent of a {@code null} {@link ModelProcessingPhase}.
52 public static final byte NULL = 0;
54 * Corresponds to {@link ModelProcessingPhase#INIT}.
56 public static final byte INIT = 1;
58 * Corresponds to {@link ModelProcessingPhase#SOURCE_PRE_LINKAGE}.
60 public static final byte SOURCE_PRE_LINKAGE = 2;
62 * Corresponds to {@link ModelProcessingPhase#SOURCE_LINKAGE}.
64 public static final byte SOURCE_LINKAGE = 3;
66 * Corresponds to {@link ModelProcessingPhase#STATEMENT_DEFINITION}.
68 public static final byte STATEMENT_DEFINITION = 4;
70 * Corresponds to {@link ModelProcessingPhase#FULL_DECLARATION}.
72 public static final byte FULL_DECLARATION = 5;
74 * Corresponds to {@link ModelProcessingPhase#EFFECTIVE_MODEL}.
76 public static final byte EFFECTIVE_MODEL = 6;
78 private ExecutionOrder() {
84 * Members of this enum at their {@link #executionOrder} offset, with {@code 0} being reserved as {@code null}.
86 private static final ModelProcessingPhase[] BY_EXECUTION_ORDER;
88 // BY_EXECUTION_ORDER initialization. The array has a semantic tie-in on ExectionOrder values, which has to follow
89 // its rules. Since we are one-time indexing, let's make a thorough job of it and verify that everything is declared
92 final ModelProcessingPhase[] values = values();
93 final ModelProcessingPhase[] tmp = new ModelProcessingPhase[values.length + 1];
95 for (ModelProcessingPhase phase : values) {
96 final byte offset = phase.executionOrder;
97 verify(offset > 0, "Invalid execution order in %s", phase);
99 final ModelProcessingPhase existing = tmp[offset];
100 verify(existing == null, "Execution order %s clash with %s", offset, existing);
101 verify(tmp[offset - 1] == phase.previousPhase, "Illegal previous phase of %s", phase);
105 BY_EXECUTION_ORDER = tmp;
108 private final @Nullable ModelProcessingPhase previousPhase;
109 private final byte executionOrder;
111 @SuppressFBWarnings(value = "NP_STORE_INTO_NONNULL_FIELD",
112 justification = "https://github.com/spotbugs/spotbugs/issues/743")
114 ModelProcessingPhase() {
115 previousPhase = null;
116 executionOrder = ExecutionOrder.INIT;
119 ModelProcessingPhase(final ModelProcessingPhase previousPhase, final int executionOrder) {
120 this.previousPhase = requireNonNull(previousPhase);
121 this.executionOrder = (byte) executionOrder;
125 * Return the preceding phase, or null if this phase is the first one.
127 * @return Preceding phase, if there is one
129 public @Nullable ModelProcessingPhase getPreviousPhase() {
130 return previousPhase;
134 * Determine whether this processing phase is implied to have completed by completion of some other phase.
135 * Algebraically this means that other is not null and is either this phase or its {@link #getPreviousPhase()} chain
136 * contains this phase.
138 * @param other Other phase
139 * @return True if this phase completes no later than specified phase.
141 public boolean isCompletedBy(final @Nullable ModelProcessingPhase other) {
142 return other != null && ordinal() <= other.ordinal();
146 * Return the execution order, which is a value in range {@code 1..127}.
148 * @return Execution order
150 public byte executionOrder() {
151 return executionOrder;
155 * Return the {@link ModelProcessingPhase} corresponding to a {@link ExecutionOrder} value.
157 * @param executionOrder Execution order
158 * @return Corresponding value, or null for {@link ExecutionOrder#NULL}
159 * @throws IllegalArgumentException if the execution order is invalid
161 public static @Nullable ModelProcessingPhase ofExecutionOrder(final byte executionOrder) {
163 return BY_EXECUTION_ORDER[executionOrder];
164 } catch (ArrayIndexOutOfBoundsException e) {
165 throw new IllegalArgumentException(e);