Refactoring: Changed `Profile` from `class` to `enum`

This enables to iterate the enum values which simplifies the entire class/enum quite a lot:
* New profiles just need to be added to enum
* Order can be replaced by `ordinal`

Enum order now is also used for profile comparison which eliminates a huge part of the class/enum.
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ef2649e..dea7036 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1985,6 +1985,9 @@
       - name: Extract
         run: tar --zstd -xf build.tar.zst
 
+      - name: enterprise/j2ee.core
+        run: ant $OPTS -f enterprise/j2ee.core test
+
       - name: enterprise/micronaut
         run: .github/retry.sh ant $OPTS -f enterprise/micronaut test
 
diff --git a/enterprise/j2ee.core/nbproject/org-netbeans-modules-j2ee-core.sig b/enterprise/j2ee.core/nbproject/org-netbeans-modules-j2ee-core.sig
index 200cb78..72f72fa 100644
--- a/enterprise/j2ee.core/nbproject/org-netbeans-modules-j2ee-core.sig
+++ b/enterprise/j2ee.core/nbproject/org-netbeans-modules-j2ee-core.sig
@@ -1,5 +1,26 @@
 #Signature file v4.1
-#Version 1.45
+#Version 1.46
+
+CLSS public abstract interface java.io.Serializable
+
+CLSS public abstract interface java.lang.Comparable<%0 extends java.lang.Object>
+meth public abstract int compareTo({java.lang.Comparable%0})
+
+CLSS public abstract java.lang.Enum<%0 extends java.lang.Enum<{java.lang.Enum%0}>>
+cons protected init(java.lang.String,int)
+intf java.io.Serializable
+intf java.lang.Comparable<{java.lang.Enum%0}>
+meth protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException
+meth protected final void finalize()
+meth public final boolean equals(java.lang.Object)
+meth public final int compareTo({java.lang.Enum%0})
+meth public final int hashCode()
+meth public final int ordinal()
+meth public final java.lang.Class<{java.lang.Enum%0}> getDeclaringClass()
+meth public final java.lang.String name()
+meth public java.lang.String toString()
+meth public static <%0 extends java.lang.Enum<{%%0}>> {%%0} valueOf(java.lang.Class<{%%0}>,java.lang.String)
+supr java.lang.Object
 
 CLSS public java.lang.Object
 cons public init()
@@ -15,7 +36,7 @@
 meth public int hashCode()
 meth public java.lang.String toString()
 
-CLSS public final org.netbeans.api.j2ee.core.Profile
+CLSS public final !enum org.netbeans.api.j2ee.core.Profile
 fld public final static java.util.Comparator<org.netbeans.api.j2ee.core.Profile> UI_COMPARATOR
 fld public final static org.netbeans.api.j2ee.core.Profile J2EE_13
 fld public final static org.netbeans.api.j2ee.core.Profile J2EE_14
@@ -44,6 +65,8 @@
 meth public static org.netbeans.api.j2ee.core.Profile fromPropertiesString(java.lang.String)
  anno 0 org.netbeans.api.annotations.common.CheckForNull()
  anno 1 org.netbeans.api.annotations.common.NullAllowed()
-supr java.lang.Object
-hfds bundleKey,order,propertiesString
+meth public static org.netbeans.api.j2ee.core.Profile valueOf(java.lang.String)
+meth public static org.netbeans.api.j2ee.core.Profile[] values()
+supr java.lang.Enum<org.netbeans.api.j2ee.core.Profile>
+hfds propertiesString
 
diff --git a/enterprise/j2ee.core/src/org/netbeans/api/j2ee/core/Bundle.properties b/enterprise/j2ee.core/src/org/netbeans/api/j2ee/core/Bundle.properties
deleted file mode 100644
index 289bc64..0000000
--- a/enterprise/j2ee.core/src/org/netbeans/api/j2ee/core/Bundle.properties
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-#
-
-J2EE13.displayName=J2EE 1.3
-J2EE14.displayName=J2EE 1.4
-JavaEE5.displayName=Java EE 5
-JavaEE6Full.displayName=Java EE 6
-JavaEE6Web.displayName=Java EE 6 Web
-JavaEE7Full.displayName=Java EE 7
-JavaEE7Web.displayName=Java EE 7 Web
-JavaEE8Full.displayName=Java EE 8
-JavaEE8Web.displayName=Java EE 8 Web
-JakartaEE8Full.displayName=Jakarta EE 8
-JakartaEE8Web.displayName=Jakarta EE 8 Web
-JakartaEE9Full.displayName=Jakarta EE 9
-JakartaEE9Web.displayName=Jakarta EE 9 Web
-JakartaEE91Full.displayName=Jakarta EE 9.1
-JakartaEE91Web.displayName=Jakarta EE 9.1 Web
-JakartaEE10Full.displayName=Jakarta EE 10
-JakartaEE10Web.displayName=Jakarta EE 10 Web
diff --git a/enterprise/j2ee.core/src/org/netbeans/api/j2ee/core/Profile.java b/enterprise/j2ee.core/src/org/netbeans/api/j2ee/core/Profile.java
index 189e05a..743eb3e 100644
--- a/enterprise/j2ee.core/src/org/netbeans/api/j2ee/core/Profile.java
+++ b/enterprise/j2ee.core/src/org/netbeans/api/j2ee/core/Profile.java
@@ -24,75 +24,82 @@
 import org.netbeans.api.annotations.common.NonNull;
 import org.netbeans.api.annotations.common.NullAllowed;
 import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
 
 /**
  * Represents the defined Java EE profiles.
  *
  * @author Petr Hejl
  */
-public final class Profile {
+public enum Profile {
 
-    public static final Comparator<Profile> UI_COMPARATOR = new Comparator<Profile>() {
-
-        @Override
-        public int compare(Profile o1, Profile o2) {
-            return -(o1.order - o2.order);
-        }
-    };
+    // !!! ATTENTION: BE AWARE OF THE ENUM ORDER! It controls compatibility and UI position.
+    // Do not ever change name of this constant - it is copied from j2eeserver
+    @Messages("J2EE_13.displayName=J2EE 1.3")
+    J2EE_13("1.3"),
 
     // Do not ever change name of this constant - it is copied from j2eeserver
-    public static final Profile J2EE_13  = new Profile(1, "1.3", null, "J2EE13.displayName");
+    @Messages("J2EE_14.displayName=J2EE 1.4")
+    J2EE_14("1.4"),
 
     // Do not ever change name of this constant - it is copied from j2eeserver
-    public static final Profile J2EE_14  = new Profile(2, "1.4", null, "J2EE14.displayName");
+    @Messages("JAVA_EE_5.displayName=Java EE 5")
+    JAVA_EE_5("1.5"),
 
-    // Do not ever change name of this constant - it is copied from j2eeserver
-    public static final Profile JAVA_EE_5  = new Profile(3, "1.5", null, "JavaEE5.displayName");
+    @Messages("JAVA_EE_6_WEB.displayName=Java EE 6 Web")
+    JAVA_EE_6_WEB("1.6", "web"),
 
-    public static final Profile JAVA_EE_6_FULL  = new Profile(4, "1.6", null, "JavaEE6Full.displayName");
+    @Messages("JAVA_EE_6_FULL.displayName=Java EE 6")
+    JAVA_EE_6_FULL("1.6"),
 
-    public static final Profile JAVA_EE_6_WEB  = new Profile(5, "1.6", "web", "JavaEE6Web.displayName");
+    @Messages("JAVA_EE_7_WEB.displayName=Java EE 7 Web")
+    JAVA_EE_7_WEB("1.7", "web"),
 
-    public static final Profile JAVA_EE_7_FULL  = new Profile(6, "1.7", null, "JavaEE7Full.displayName");
+    @Messages("JAVA_EE_7_FULL.displayName=Java EE 7")
+    JAVA_EE_7_FULL("1.7"),
 
-    public static final Profile JAVA_EE_7_WEB  = new Profile(7, "1.7", "web", "JavaEE7Web.displayName");
+    @Messages("JAVA_EE_8_WEB.displayName=Java EE 8 Web")
+    JAVA_EE_8_WEB("1.8", "web"),
 
-    public static final Profile JAVA_EE_8_FULL  = new Profile(8, "1.8", null, "JavaEE8Full.displayName");
+    @Messages("JAVA_EE_8_FULL.displayName=Java EE 8")
+    JAVA_EE_8_FULL("1.8"),
 
-    public static final Profile JAVA_EE_8_WEB  = new Profile(9, "1.8", "web", "JavaEE8Web.displayName");
+    @Messages("JAKARTA_EE_8_WEB.displayName=Jakarta EE 8 Web")
+    JAKARTA_EE_8_WEB("8.0", "web"),
 
-    public static final Profile JAKARTA_EE_8_FULL  = new Profile(10, "8.0", null, "JakartaEE8Full.displayName");
+    @Messages("JAKARTA_EE_8_FULL.displayName=Jakarta EE 8")
+    JAKARTA_EE_8_FULL("8.0"),
 
-    public static final Profile JAKARTA_EE_8_WEB  = new Profile(11, "8.0", "web", "JakartaEE8Web.displayName");
+    @Messages("JAKARTA_EE_9_WEB.displayName=Jakarta EE 9 Web")
+    JAKARTA_EE_9_WEB("9.0", "web"),
 
-    public static final Profile JAKARTA_EE_9_WEB  = new Profile(12, "9.0", "web", "JakartaEE9Web.displayName");
+    @Messages("JAKARTA_EE_9_FULL.displayName=Jakarta EE 9")
+    JAKARTA_EE_9_FULL("9.0"),
 
-    public static final Profile JAKARTA_EE_9_FULL  = new Profile(13, "9.0", null, "JakartaEE9Full.displayName");
-    
-    public static final Profile JAKARTA_EE_9_1_WEB  = new Profile(14, "9.1", "web", "JakartaEE91Web.displayName");
+    @Messages("JAKARTA_EE_9_1_WEB.displayName=Jakarta EE 9.1 Web")
+    JAKARTA_EE_9_1_WEB("9.1", "web"),
 
-    public static final Profile JAKARTA_EE_9_1_FULL  = new Profile(15, "9.1", null, "JakartaEE91Full.displayName");
+    @Messages("JAKARTA_EE_9_1_FULL.displayName=Jakarta EE 9.1")
+    JAKARTA_EE_9_1_FULL("9.1"),
 
-    public static final Profile JAKARTA_EE_10_WEB  = new Profile(16, "10", "web", "JakartaEE10Web.displayName");
+    @Messages("JAKARTA_EE_10_WEB.displayName=Jakarta EE 10 Web")
+    JAKARTA_EE_10_WEB("10", "web"),
 
-    public static final Profile JAKARTA_EE_10_FULL  = new Profile(17, "10", null, "JakartaEE10Full.displayName");
+    @Messages("JAKARTA_EE_10_FULL.displayName=Jakarta EE 10")
+    JAKARTA_EE_10_FULL("10");
+    // !!! ATTENTION: BE AWARE OF THE ENUM ORDER! It controls compatibility and UI position.
 
-    private final int order;
+    public static final Comparator<Profile> UI_COMPARATOR = (Profile o1, Profile o2) -> -(o1.ordinal() - o2.ordinal());
 
     // cache
     private final String propertiesString;
 
-    private final String bundleKey;
+    private Profile(String canonicalName) {
+        this.propertiesString = canonicalName;
+    }
 
-    private Profile(int order, String canonicalName, String profile, String bundleKey) {
-        this.order = order;
-        this.bundleKey = bundleKey;
-
-        StringBuilder builder = new StringBuilder(canonicalName);
-        if (profile != null) {
-            builder.append("-").append(profile); // NOI18N
-        }
-        this.propertiesString = builder.toString();
+    private Profile(String canonicalName, String profile) {
+        this.propertiesString = canonicalName + "-" + profile;
     }
 
     /**
@@ -102,7 +109,7 @@
      */
     @NonNull
     public String getDisplayName() {
-        return NbBundle.getMessage(Profile.class, bundleKey);
+        return NbBundle.getMessage(Profile.class, this.name() + ".displayName");
     }
 
     @NonNull
@@ -130,7 +137,7 @@
      * @since 1.19
      */
     public boolean isAtLeast(@NonNull Profile profile) {
-        return isVersionEqualOrHigher(this, profile);
+        return this.ordinal() >= profile.ordinal();
     }
 
     @Override
@@ -140,134 +147,20 @@
 
     @CheckForNull
     public static Profile fromPropertiesString(@NullAllowed String value) {
-        String valueMinusQuotes = value;
-        if(value != null && value.contains("\"")){
-            valueMinusQuotes = value.replace("\"","");
+        if (value == null) {
+            return null;
         }
-        if (J2EE_13.toPropertiesString().equals(valueMinusQuotes)) {
-            return J2EE_13;
-        } else if (J2EE_14.toPropertiesString().equals(valueMinusQuotes)) {
-            return J2EE_14;
-        } else if (JAVA_EE_5.toPropertiesString().equals(valueMinusQuotes)) {
-            return JAVA_EE_5;
-        } else if (JAVA_EE_6_FULL.toPropertiesString().equals(valueMinusQuotes)
-                || "EE_6_FULL".equals(value)){ // NOI18N
-            return JAVA_EE_6_FULL;
-        } else if (JAVA_EE_6_WEB.toPropertiesString().equals(valueMinusQuotes)
-                || "EE_6_WEB".equals(value)) {
-            return JAVA_EE_6_WEB;
-        } else if (JAVA_EE_7_FULL.toPropertiesString().equals(valueMinusQuotes)
-                || "EE_7_FULL".equals(value)) { // NOI18N
-            return JAVA_EE_7_FULL;
-        } else if (JAVA_EE_7_WEB.toPropertiesString().equals(valueMinusQuotes)
-                || "EE_7_WEB".equals(value)) {
-            return JAVA_EE_7_WEB;
-        } else if (JAVA_EE_8_FULL.toPropertiesString().equals(valueMinusQuotes)
-                || "EE_8_FULL".equals(value)) { // NOI18N
-            return JAVA_EE_8_FULL;
-        } else if (JAVA_EE_8_WEB.toPropertiesString().equals(valueMinusQuotes)
-                || "EE_8_WEB".equals(value)) {
-            return JAVA_EE_8_WEB;
-        } else if (JAKARTA_EE_8_FULL.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_8_FULL".equals(value)) {
-            return JAKARTA_EE_8_FULL;
-        } else if (JAKARTA_EE_8_WEB.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_8_WEB".equals(value)) {
-            return JAKARTA_EE_8_WEB;
-        } else if (JAKARTA_EE_9_FULL.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_9_FULL".equals(value)) {
-            return JAKARTA_EE_9_FULL;
-        } else if (JAKARTA_EE_9_WEB.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_9_WEB".equals(value)) {
-            return JAKARTA_EE_9_WEB;
-        } else if (JAKARTA_EE_9_1_FULL.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_9_1_FULL".equals(value)) {
-            return JAKARTA_EE_9_1_FULL;
-        } else if (JAKARTA_EE_9_1_WEB.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_9_1_WEB".equals(value)) {
-            return JAKARTA_EE_9_1_WEB;
-        } else if (JAKARTA_EE_10_FULL.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_10_FULL".equals(value)) {
-            return JAKARTA_EE_10_FULL;
-        } else if (JAKARTA_EE_10_WEB.toPropertiesString().equals(valueMinusQuotes)
-                || "JAKARTA_EE_10_WEB".equals(value)) {
-            return JAKARTA_EE_10_WEB;
-        } else {
-          return null;
-        }
-    }
 
-    private static String getProfileVersion(@NonNull Profile profile) {
-        String profileDetails = profile.toPropertiesString();
-        int indexOfDash = profileDetails.indexOf("-");
-        if (indexOfDash != -1) {
-            return profileDetails.substring(0, indexOfDash);
-        }
-        return profileDetails;
-    }
+        String valueMinusQuotes = value.replace("\"","");
 
-    private static boolean compareWebAndFull(@NonNull Profile profileToCompare, @NonNull Profile comparingVersion) {
-        boolean isThisFullProfile = isFullProfile(profileToCompare);
-        boolean isParamFullProfile = isFullProfile(comparingVersion);
-        if (isThisFullProfile && isParamFullProfile) {
-            // Both profiles are Java EE Full
-            return true;
-        }
-        if (!isThisFullProfile && !isParamFullProfile) {
-            // Both profiles are Java EE Web
-            return true;
-        }
-        if (isThisFullProfile && !isParamFullProfile) {
-            // profileToCompare is Java EE Full profile and comparingVersion is only Java EEWeb profile
-            return true;
-        }
-        return false;
-    }
-
-    private static boolean isFullProfile(@NonNull Profile profile) {
-        final String profileDetails = profile.toPropertiesString();
-        if (profileDetails.indexOf("-") == -1) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Compares if the first given profile has equal or higher Java EE version
-     * in comparison to the second profile.
-     *
-     * Please be aware of the following rules:
-     * <br/><br/>
-     *
-     * 1) Each Java EE X version is considered as lower than Java EE X+1 version
-     * (this applies regardless on Web/Full specification and in reality it means
-     * that even Java EE 6 Full version is considered as lower than Java EE 7 Web)
-     * <br/><br/>
-     *
-     * 2) Each Java EE X Web version is considered as lower than Java EE X Full
-     * <br/>
-     *
-     * @param profileToCompare profile that we want to compare
-     * @param comparingVersion version which we are comparing with
-     * @return <code>true</code> if the profile version is equal or higher in
-     *         comparison with the second one, <code>false</code> otherwise
-     * @since 1.19
-     */
-    private static boolean isVersionEqualOrHigher(@NonNull Profile profileToCompare, @NonNull Profile comparingVersion) {
-        int comparisonResult = Profile.UI_COMPARATOR.compare(profileToCompare, comparingVersion);
-        if (comparisonResult == 0) {
-            // The same version for both
-            return true;
-        } else {
-            String profileToCompareVersion = getProfileVersion(profileToCompare);
-            String comparingProfileVersion = getProfileVersion(comparingVersion);
-            if (profileToCompareVersion.equals(comparingProfileVersion)) {
-                return compareWebAndFull(profileToCompare, comparingVersion);
-            } else {
-                // profileToCompare has lower version than comparingVersion
-                return comparisonResult <= 0;
+        for (Profile profile : Profile.values()) {
+            if (profile.toPropertiesString().equals(valueMinusQuotes)
+                    || profile.name().equals(valueMinusQuotes)
+                    || (valueMinusQuotes.startsWith("EE_") && profile.name().endsWith(valueMinusQuotes))) {
+                return profile;
             }
         }
-    }
 
+        return null;
+    }
 }
diff --git a/enterprise/j2ee.core/test/unit/src/org/netbeans/api/j2ee/core/ProfileTest.java b/enterprise/j2ee.core/test/unit/src/org/netbeans/api/j2ee/core/ProfileTest.java
index c5fe669..5535d2d 100644
--- a/enterprise/j2ee.core/test/unit/src/org/netbeans/api/j2ee/core/ProfileTest.java
+++ b/enterprise/j2ee.core/test/unit/src/org/netbeans/api/j2ee/core/ProfileTest.java
@@ -59,11 +59,12 @@
         assertEquals(Profile.JAKARTA_EE_9_1_FULL, Profile.fromPropertiesString("JAKARTA_EE_9_1_FULL"));
         assertEquals(Profile.JAKARTA_EE_9_1_WEB, Profile.fromPropertiesString("9.1-web"));
         assertEquals(Profile.JAKARTA_EE_9_1_WEB, Profile.fromPropertiesString("JAKARTA_EE_9_1_WEB"));
-        assertEquals(Profile.JAKARTA_EE_10_FULL, Profile.fromPropertiesString("10.0"));
+        assertEquals(Profile.JAKARTA_EE_10_FULL, Profile.fromPropertiesString("10"));
         assertEquals(Profile.JAKARTA_EE_10_FULL, Profile.fromPropertiesString("JAKARTA_EE_10_FULL"));
-        assertEquals(Profile.JAKARTA_EE_10_WEB, Profile.fromPropertiesString("10.0-web"));
+        assertEquals(Profile.JAKARTA_EE_10_WEB, Profile.fromPropertiesString("10-web"));
         assertEquals(Profile.JAKARTA_EE_10_WEB, Profile.fromPropertiesString("JAKARTA_EE_10_WEB"));
         assertNull(Profile.fromPropertiesString("something"));
+        assertNull(Profile.fromPropertiesString(null));
     }
 
     public void testIsHigherJavaEEVersionJavaEE5() {
@@ -228,9 +229,15 @@
         assertFalse(Profile.JAKARTA_EE_8_FULL.isAtLeast(Profile.JAKARTA_EE_10_WEB));
         assertFalse(Profile.JAKARTA_EE_9_WEB.isAtLeast(Profile.JAKARTA_EE_10_WEB));
         assertFalse(Profile.JAKARTA_EE_9_FULL.isAtLeast(Profile.JAKARTA_EE_10_WEB));
-        assertTrue(Profile.JAKARTA_EE_9_1_WEB.isAtLeast(Profile.JAKARTA_EE_10_WEB));
-        assertTrue(Profile.JAKARTA_EE_9_1_FULL.isAtLeast(Profile.JAKARTA_EE_10_WEB));
+        assertFalse(Profile.JAKARTA_EE_9_1_WEB.isAtLeast(Profile.JAKARTA_EE_10_WEB));
+        assertFalse(Profile.JAKARTA_EE_9_1_FULL.isAtLeast(Profile.JAKARTA_EE_10_WEB));
         assertTrue(Profile.JAKARTA_EE_10_WEB.isAtLeast(Profile.JAKARTA_EE_10_WEB));
         assertTrue(Profile.JAKARTA_EE_10_FULL.isAtLeast(Profile.JAKARTA_EE_10_WEB));
     }
+
+    public void testAllEnumsHaveDisplayNames() {
+        for (Profile profile : Profile.values()) {
+            profile.getDisplayName();
+        }
+    }
 }