View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.lifecycle.internal;
20  
21  import java.util.Map;
22  import java.util.Objects;
23  import java.util.WeakHashMap;
24  
25  /**
26   * Represents a parsed phase identifier.
27   */
28  public class PhaseId {
29      /**
30       * Interned {@link PhaseId} instances.
31       */
32      private static final Map<String, PhaseId> INSTANCES = new WeakHashMap<>();
33  
34      /**
35       * The execution point of this {@link PhaseId}.
36       */
37      private final PhaseExecutionPoint executionPoint;
38  
39      /**
40       * The static phase that this dynamic phase belongs to.
41       */
42      private final String phase;
43  
44      /**
45       * The priority of this dynamic phase within the static phase.
46       */
47      private final int priority;
48  
49      /**
50       * Parses the phase identifier.
51       *
52       * @param phase the phase identifier.
53       * @return the {@link PhaseId}.
54       */
55      public static synchronized PhaseId of(String phase) {
56          return INSTANCES.computeIfAbsent(phase, PhaseId::new);
57      }
58  
59      /**
60       * Constructor.
61       *
62       * @param phase the phase identifier string.
63       */
64      private PhaseId(String phase) {
65          int phaseStart;
66          if (phase.startsWith(PhaseExecutionPoint.BEFORE.prefix())) {
67              executionPoint = PhaseExecutionPoint.BEFORE;
68              phaseStart = PhaseExecutionPoint.BEFORE.prefix().length();
69          } else if (phase.startsWith(PhaseExecutionPoint.AFTER.prefix())) {
70              executionPoint = PhaseExecutionPoint.AFTER;
71              phaseStart = PhaseExecutionPoint.AFTER.prefix().length();
72          } else {
73              executionPoint = PhaseExecutionPoint.AT;
74              phaseStart = 0;
75          }
76          int phaseEnd = phase.indexOf('[');
77          if (phaseEnd == -1) {
78              priority = 0;
79              this.phase = phase.substring(phaseStart);
80          } else {
81              int priorityEnd = phase.lastIndexOf(']');
82              boolean hasPriority;
83              int priority;
84              if (priorityEnd < phaseEnd + 1) {
85                  priority = 0;
86                  hasPriority = false;
87              } else {
88                  try {
89                      priority = Integer.parseInt(phase.substring(phaseEnd + 1, priorityEnd));
90                      hasPriority = true;
91                  } catch (NumberFormatException e) {
92                      // priority must be an integer
93                      priority = 0;
94                      hasPriority = false;
95                  }
96              }
97              if (hasPriority) {
98                  this.phase = phase.substring(phaseStart, phaseEnd);
99                  this.priority = priority;
100             } else {
101                 this.phase = phase.substring(phaseStart);
102                 this.priority = 0;
103             }
104         }
105     }
106 
107     @Override
108     public boolean equals(Object o) {
109         if (this == o) {
110             return true;
111         } else if (o == null || getClass() != o.getClass()) {
112             return false;
113         } else {
114             PhaseId phaseId = (PhaseId) o;
115             return Objects.equals(executionPoint(), phaseId.executionPoint())
116                     && Objects.equals(phase(), phaseId.phase())
117                     && Objects.equals(priority(), phaseId.priority());
118         }
119     }
120 
121     @Override
122     public int hashCode() {
123         return Objects.hash(executionPoint(), phase(), priority());
124     }
125 
126     @Override
127     public String toString() {
128         return executionPoint().prefix() + phase() + (priority() != 0 ? "[" + priority() + ']' : "");
129     }
130 
131     public PhaseExecutionPoint executionPoint() {
132         return executionPoint;
133     }
134 
135     public String phase() {
136         return phase;
137     }
138 
139     public int priority() {
140         return priority;
141     }
142 }