You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/03/05 12:20:07 UTC

[isis] branch master updated: ISIS-2553: simplify findOrphaned permission logic

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new f489620  ISIS-2553: simplify findOrphaned permission logic
f489620 is described below

commit f489620deca144a50bd7970edaa0dda0892f480a
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Mar 5 13:19:59 2021 +0100

    ISIS-2553: simplify findOrphaned permission logic
    
    in turns allows some code removal
---
 .../services/appfeat/ApplicationFeatureId.java     |  5 +-
 .../appfeat/ApplicationFeatureRepository.java      | 15 ----
 .../ApplicationFeatureRepositoryDefault.java       | 62 ++++-----------
 .../ApplicationFeatureRepositoryDefaultTest.java   |  2 +-
 .../api/permission/ApplicationPermission.java      |  6 +-
 .../jdo/dom/permission/ApplicationPermission.java  |  9 ++-
 .../ApplicationPermissionRepository.java           | 83 +++------------------
 .../jpa/dom/permission/ApplicationPermission.java  |  4 +-
 .../ApplicationPermissionRepository.java           | 87 +++-------------------
 9 files changed, 50 insertions(+), 223 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureId.java b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureId.java
index f9ab7ab..89d504b 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureId.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureId.java
@@ -206,7 +206,7 @@ implements
 
     @Programmatic
     public String getFullyQualifiedName() {
-        final StringBuilder buf = new StringBuilder();
+        val buf = new StringBuilder();
         buf.append(getNamespace());
         if(getTypeSimpleName() != null) {
             buf.append(".").append(getTypeSimpleName());
@@ -222,8 +222,7 @@ implements
         if (getTypeSimpleName() == null) {
             return null;
         }
-
-        final StringBuilder buf = new StringBuilder();
+        val buf = new StringBuilder();
         if(!_Strings.isNullOrEmpty(getNamespace())) {
             buf.append(getNamespace()).append(".");
         }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java
index 01293e9..da0b828 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java
@@ -34,25 +34,10 @@ public interface ApplicationFeatureRepository  {
     //TODO[2553] why return String, when AppFeatId is now API
     SortedSet<String> namespaceNames();
 
-//    SortedSet<String> namespaceNamesContainingSort(
-//            ApplicationMemberSort memberSort);
-
-    //TODO[2553] remove, only used by orphaned search, which can be done much simpler
-    SortedSet<String> classNamesContainedIn(
-            String packageFqn,
-            ApplicationMemberSort memberSort);
-
     //TODO[2553] remove or rename->logicalTypeSimpleNamesRecursivelyContainedInNamespace
     SortedSet<String> classNamesRecursivelyContainedIn(
             String packageFqn);
 
-    //TODO[2553] why return String, when AppFeatId is now API
-    SortedSet<String> memberNamesOf(
-            String packageFqn,
-            String className,
-            ApplicationMemberSort memberSort);
-
-    
     Map<String, ApplicationFeatureId> getFeatureIdentifiersByName();
 
     ApplicationFeature findFeature(ApplicationFeatureId featureId);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
index 6311636..dd9bdb6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
@@ -78,8 +78,8 @@ implements ApplicationFeatureRepository {
 
     // -- caches
     private Map<String, ApplicationFeatureId> featureIdentifiersByName;
-    final SortedMap<ApplicationFeatureId, ApplicationFeature> packageFeatures = _Maps.newTreeMap();
-    private final SortedMap<ApplicationFeatureId, ApplicationFeature> classFeatures = _Maps.newTreeMap();
+    final SortedMap<ApplicationFeatureId, ApplicationFeature> namespaceFeatures = _Maps.newTreeMap();
+    private final SortedMap<ApplicationFeatureId, ApplicationFeature> typeFeatures = _Maps.newTreeMap();
     private final SortedMap<ApplicationFeatureId, ApplicationFeature> memberFeatures = _Maps.newTreeMap();
     private final SortedMap<ApplicationFeatureId, ApplicationFeature> propertyFeatures = _Maps.newTreeMap();
     private final SortedMap<ApplicationFeatureId, ApplicationFeature> collectionFeatures = _Maps.newTreeMap();
@@ -134,8 +134,8 @@ implements ApplicationFeatureRepository {
         }
         
         val featuresByName = new HashMap<String, ApplicationFeatureId>();
-        visitFeatureIdentifierByName(packageFeatures, featuresByName::put);
-        visitFeatureIdentifierByName(classFeatures, featuresByName::put);
+        visitFeatureIdentifierByName(namespaceFeatures, featuresByName::put);
+        visitFeatureIdentifierByName(typeFeatures, featuresByName::put);
         visitFeatureIdentifierByName(memberFeatures, featuresByName::put);
         this.featureIdentifiersByName = Collections.unmodifiableMap(featuresByName);
     }
@@ -143,7 +143,7 @@ implements ApplicationFeatureRepository {
     private void visitFeatureIdentifierByName(
             final Map<ApplicationFeatureId, ApplicationFeature> map, 
             final BiConsumer<String, ApplicationFeatureId> onEntry) {
-        map.forEach((k, v)->onEntry.accept(k.toString(), k));
+        map.forEach((k, v)->onEntry.accept(k.getFullyQualifiedName(), k));
     }
 
     void createApplicationFeaturesFor(final ObjectSpecification spec) {
@@ -170,7 +170,7 @@ implements ApplicationFeatureRepository {
         // (later on it may get removed if the class turns out to have no features,
         // but we require it in the map for the next bit).
         final ApplicationFeature classFeature = newFeature(classFeatureId);
-        classFeatures.put(classFeatureId, classFeature);
+        typeFeatures.put(classFeatureId, classFeature);
 
         // add members
         boolean addedMembers = false;
@@ -194,7 +194,7 @@ implements ApplicationFeatureRepository {
 
         if (!addedMembers) {
             // remove this class feature, since it turned out to have no members
-            classFeatures.remove(classFeatureId);
+            typeFeatures.remove(classFeatureId);
             return;
         }
 
@@ -249,7 +249,7 @@ implements ApplicationFeatureRepository {
 
     private ApplicationFeature newPackage(final ApplicationFeatureId packageId) {
         final ApplicationFeature parentPackage = newFeature(packageId);
-        packageFeatures.put(packageId, parentPackage);
+        namespaceFeatures.put(packageId, parentPackage);
         return parentPackage;
     }
 
@@ -390,13 +390,13 @@ implements ApplicationFeatureRepository {
 
     public ApplicationFeature findNamespace(final ApplicationFeatureId featureId) {
         initializeIfRequired();
-        return packageFeatures.get(featureId);
+        return namespaceFeatures.get(featureId);
     }
 
 
     public ApplicationFeature findLogicalType(final ApplicationFeatureId featureId) {
         initializeIfRequired();
-        return classFeatures.get(featureId);
+        return typeFeatures.get(featureId);
     }
 
 
@@ -428,13 +428,13 @@ implements ApplicationFeatureRepository {
     @Override
     public Collection<ApplicationFeature> allNamespaces() {
         initializeIfRequired();
-        return packageFeatures.values();
+        return namespaceFeatures.values();
     }
 
     @Override
     public Collection<ApplicationFeature> allTypes() {
         initializeIfRequired();
-        return classFeatures.values();
+        return typeFeatures.values();
     }
 
     @Override
@@ -478,24 +478,6 @@ implements ApplicationFeatureRepository {
     }
 
     @Override
-    public SortedSet<String> classNamesContainedIn(
-            final String namespace, 
-            final ApplicationMemberSort memberSort) {
-        
-        initializeIfRequired();
-        final ApplicationFeatureId namespaceId = ApplicationFeatureId.newNamespace(namespace);
-        final ApplicationFeature namespaceFeat = findNamespace(namespaceId);
-        if (namespaceFeat == null) {
-            return Collections.emptySortedSet();
-        }
-        final SortedSet<ApplicationFeatureId> contents = namespaceFeat.getContents();
-        return contents.stream()
-                .filter(_Predicates.isLogicalTypeContaining(memberSort, this))
-                .map(ApplicationFeatureId::getTypeSimpleName)
-                .collect(_Sets.toUnmodifiableSorted());
-    }
-
-    @Override
     public SortedSet<String> classNamesRecursivelyContainedIn(final String packageFqn) {
         initializeIfRequired();
         final ApplicationFeatureId packageId = ApplicationFeatureId.newNamespace(packageFqn);
@@ -503,29 +485,11 @@ implements ApplicationFeatureRepository {
         if (pkg == null) {
             return Collections.emptySortedSet();
         }
-        final Set<ApplicationFeatureId> classIds = this.classFeatures.keySet();
+        final Set<ApplicationFeatureId> classIds = this.typeFeatures.keySet();
         return classIds.stream()
                 .filter(_Predicates.isLogicalTypeRecursivelyWithin(packageId))
                 .map(ApplicationFeatureId::getTypeSimpleName)
                 .collect(_Sets.toUnmodifiableSorted());
     }
 
-    @Override
-    public SortedSet<String> memberNamesOf(
-            final String packageFqn,
-            final String className,
-            final ApplicationMemberSort memberSort) {
-        initializeIfRequired();
-        final ApplicationFeatureId classId = ApplicationFeatureId.newType(packageFqn + "." + className);
-        final ApplicationFeature cls = findLogicalType(classId);
-        if (cls == null) {
-            return Collections.emptySortedSet();
-        }
-        final SortedSet<ApplicationFeatureId> featureIds = cls.getMembersOfSort(memberSort);
-        return featureIds.stream()
-                .map(ApplicationFeatureId::getMemberName)
-                .collect(_Sets.toUnmodifiableSorted());
-    }
-    
-
 }
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
index 650f240..40f4789 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
@@ -286,7 +286,7 @@ public class ApplicationFeatureRepositoryDefaultTest {
             // given
             final ApplicationFeatureId packageId = ApplicationFeatureId.newNamespace("com.mycompany");
             final ApplicationFeature pkg = newApplicationFeature(packageId);
-            applicationFeatureRepository.packageFeatures.put(packageId, pkg);
+            applicationFeatureRepository.namespaceFeatures.put(packageId, pkg);
 
             final ApplicationFeatureId classFeatureId = ApplicationFeatureId.newType("com.mycompany.Bar");
 
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java
index 6794e46..9d7dd8c 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java
@@ -97,7 +97,7 @@ public interface ApplicationPermission {
         .append(" ").append(getMode().toString()) // Viewing|Changing
         .append(" of ");
 
-        createFeatureId()
+        asFeatureId()
         .ifPresent(featureId->{
 
             switch (featureId.getSort()) {
@@ -176,8 +176,8 @@ public interface ApplicationPermission {
     // -- HELPER
 
     @Programmatic
-    default Optional<ApplicationFeatureId> createFeatureId() {
-        return Optional.of(getFeatureSort())
+    default Optional<ApplicationFeatureId> asFeatureId() {
+        return Optional.ofNullable(getFeatureSort())
                 .map(featureSort -> ApplicationFeatureId.newFeature(featureSort, getFeatureFqn()));
     }
 
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java
index a04b71a..752ea8b 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java
@@ -111,7 +111,10 @@ import lombok.experimental.UtilityClass;
 @DomainObjectLayout(
         bookmarking = BookmarkPolicy.AS_CHILD
         )
-public class ApplicationPermission implements org.apache.isis.extensions.secman.api.permission.ApplicationPermission, Comparable<ApplicationPermission> {
+public class ApplicationPermission 
+implements 
+    org.apache.isis.extensions.secman.api.permission.ApplicationPermission, 
+    Comparable<ApplicationPermission> {
 
     private static final int TYPICAL_LENGTH_TYPE = 7;  // ApplicationFeatureType.PACKAGE is longest
 
@@ -165,7 +168,7 @@ public class ApplicationPermission implements org.apache.isis.extensions.secman.
     // -- featureId (derived property)
 
     private Optional<ApplicationFeature> getFeature() {
-        return createFeatureId()
+        return asFeatureId()
                 .map(featureId -> featureRepository.findFeature(featureId));
     }
 
@@ -292,7 +295,7 @@ public class ApplicationPermission implements org.apache.isis.extensions.secman.
         public static final Function<ApplicationPermission, ApplicationPermissionValue> AS_VALUE = 
                 (ApplicationPermission input) ->
                     new ApplicationPermissionValue(
-                            input.createFeatureId().orElseThrow(_Exceptions::noSuchElement), 
+                            input.asFeatureId().orElseThrow(_Exceptions::noSuchElement), 
                             input.getRule(), 
                             input.getMode());
 
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java
index d22e4bc..400483e 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java
@@ -21,8 +21,6 @@ package org.apache.isis.extensions.secman.jdo.dom.permission;
 import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -34,14 +32,12 @@ import org.apache.isis.applib.services.appfeat.ApplicationFeature;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureSort;
-import org.apache.isis.applib.services.appfeat.ApplicationMemberSort;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Multimaps;
 import org.apache.isis.commons.internal.collections._Multimaps.ListMultimap;
@@ -316,83 +312,26 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
     @Override
     public Collection<ApplicationPermission> findOrphaned() {
 
-        final Collection<String> namespaceNames = featureRepository.namespaceNames();
-        final Set<String> availableClasses = _Sets.newTreeSet();
-        for (String packageName : namespaceNames) {
-            appendLogicalTypes(packageName, ApplicationMemberSort.PROPERTY, availableClasses);
-            appendLogicalTypes(packageName, ApplicationMemberSort.COLLECTION, availableClasses);
-            appendLogicalTypes(packageName, ApplicationMemberSort.ACTION, availableClasses);
-        }
+        val featureNamesKnownToTheMetamodel =  
+                featureRepository.getFeatureIdentifiersByName().keySet();
 
         val orphaned = _Lists.<ApplicationPermission>newArrayList();
 
         for (val permission : allPermissions()) {
-            final ApplicationFeatureSort featureSort = permission.getFeatureSort();
-            final String featureFqn = permission.getFeatureFqn();
-
-            switch (featureSort) {
-
-            case NAMESPACE:
-                if(!namespaceNames.contains(featureFqn)) {
-                    orphaned.add(permission);
-                }
-                break;
-            case TYPE:
-                if(!availableClasses.contains(featureFqn)) {
-                    orphaned.add(permission);
-                }
-                break;
-            case MEMBER:
-
-                final List<String> split = _Strings.splitThenStream(featureFqn, "#")
-                .collect(Collectors.toList());
-
-                final String fqClassName = split.get(0);
-                final String memberName = split.get(1);
-
-                final int lastDot = fqClassName.lastIndexOf('.');
-                final String packageName = fqClassName.substring(0, lastDot);
-                final String className = fqClassName.substring(lastDot + 1);
-
-                final List<String> memberNames = memberNamesOf(packageName, className);
-
-                if(!memberNames.contains(memberName)) {
-                    orphaned.add(permission);
-                }
-                break;
+            
+            val featId = permission.asFeatureId().orElse(null);
+            if(featId==null) {
+                orphaned.add(permission);
+                continue;
+            }
+            
+            if(!featureNamesKnownToTheMetamodel.contains(featId.getFullyQualifiedName())) {
+                orphaned.add(permission);
             }
         }
 
         return orphaned;
     }
 
-    private void appendLogicalTypes(
-            final String packageName, 
-            final ApplicationMemberSort memberSort, 
-            final Set<String> availableClasses) {
-        final Collection<String> classNames = featureRepository.classNamesContainedIn(packageName, memberSort);
-        for (String className : classNames) {
-            availableClasses.add(packageName + "." + className);
-        }
-    }
-
-    private List<String> memberNamesOf(final String packageName, final String className) {
-        final List<String> memberNames = _Lists.newArrayList();
-        appendMembers(packageName, className, ApplicationMemberSort.PROPERTY, memberNames);
-        appendMembers(packageName, className, ApplicationMemberSort.COLLECTION, memberNames);
-        appendMembers(packageName, className, ApplicationMemberSort.ACTION, memberNames);
-        return memberNames;
-    }
-
-    private void appendMembers(
-            final String packageName,
-            final String className,
-            final ApplicationMemberSort getMemberSort,
-            final List<String> memberNames) {
-        final Collection<String> memberNamesOf =
-                featureRepository.memberNamesOf(packageName, className, getMemberSort);
-        memberNames.addAll(memberNamesOf);
-    }
-
 
 }
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java
index 8b0f1e6..d1c9e54 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java
@@ -180,7 +180,7 @@ implements
     // -- featureId (derived property)
 
     private Optional<ApplicationFeature> getFeature() {
-        return createFeatureId()
+        return asFeatureId()
                 .map(featureId -> featureRepository.findFeature(featureId));
     }
 
@@ -308,7 +308,7 @@ implements
         public static final Function<ApplicationPermission, ApplicationPermissionValue> AS_VALUE = 
                 (ApplicationPermission input) ->
                     new ApplicationPermissionValue(
-                            input.createFeatureId().orElseThrow(_Exceptions::noSuchElement), 
+                            input.asFeatureId().orElseThrow(_Exceptions::noSuchElement), 
                             input.getRule(), 
                             input.getMode());
 
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java
index f776a3b..787fc8a 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java
@@ -22,7 +22,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import java.util.Set;
 import java.util.stream.Collectors;
 
 import javax.inject.Inject;
@@ -35,14 +34,12 @@ import org.apache.isis.applib.services.appfeat.ApplicationFeature;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureSort;
-import org.apache.isis.applib.services.appfeat.ApplicationMemberSort;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Multimaps;
 import org.apache.isis.commons.internal.collections._Multimaps.ListMultimap;
@@ -335,86 +332,26 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
     @Override
     public Collection<ApplicationPermission> findOrphaned() {
 
-        featureRepository.getFeatureIdentifiersByName();
-        
-        final Collection<String> namespaceNames = featureRepository.namespaceNames();
-        final Set<String> availableClasses = _Sets.newTreeSet();
-        for (String packageName : namespaceNames) {
-            appendLogicalTypes(packageName, ApplicationMemberSort.PROPERTY, availableClasses);
-            appendLogicalTypes(packageName, ApplicationMemberSort.COLLECTION, availableClasses);
-            appendLogicalTypes(packageName, ApplicationMemberSort.ACTION, availableClasses);
-        }
+        val featureNamesKnownToTheMetamodel =  
+                featureRepository.getFeatureIdentifiersByName().keySet();
 
         val orphaned = _Lists.<ApplicationPermission>newArrayList();
 
-        val permissions = allPermissions();
-        for (val permission : permissions) {
-            final ApplicationFeatureSort featureType = permission.getFeatureSort();
-            final String featureFqn = permission.getFeatureFqn();
-
-            switch (featureType) {
-
-            case NAMESPACE:
-                if(!namespaceNames.contains(featureFqn)) {
-                    orphaned.add(permission);
-                }
-                break;
-            case TYPE:
-                if(!availableClasses.contains(featureFqn)) {
-                    orphaned.add(permission);
-                }
-                break;
-            case MEMBER:
-
-                final List<String> split = _Strings.splitThenStream(featureFqn, "#")
-                .collect(Collectors.toList());
-
-                final String fqClassName = split.get(0);
-                final String memberName = split.get(1);
-
-                final int lastDot = fqClassName.lastIndexOf('.');
-                final String packageName = fqClassName.substring(0, lastDot);
-                final String className = fqClassName.substring(lastDot + 1);
-
-                final List<String> memberNames = memberNamesOf(packageName, className);
-
-                if(!memberNames.contains(memberName)) {
-                    orphaned.add(permission);
-                }
-                break;
+        for (val permission : allPermissions()) {
+            
+            val featId = permission.asFeatureId().orElse(null);
+            if(featId==null) {
+                orphaned.add(permission);
+                continue;
+            }
+            
+            if(!featureNamesKnownToTheMetamodel.contains(featId.getFullyQualifiedName())) {
+                orphaned.add(permission);
             }
         }
 
         return orphaned;
     }
 
-    private void appendLogicalTypes(
-            final String packageName, 
-            final ApplicationMemberSort memberSort, 
-            final Set<String> availableClasses) {
-        final Collection<String> classNames = featureRepository.classNamesContainedIn(packageName, memberSort);
-        for (String className : classNames) {
-            availableClasses.add(packageName + "." + className);
-        }
-    }
-
-    private List<String> memberNamesOf(final String packageName, final String className) {
-        final List<String> memberNames = _Lists.newArrayList();
-        appendMembers(packageName, className, ApplicationMemberSort.PROPERTY, memberNames);
-        appendMembers(packageName, className, ApplicationMemberSort.COLLECTION, memberNames);
-        appendMembers(packageName, className, ApplicationMemberSort.ACTION, memberNames);
-        return memberNames;
-    }
-
-    private void appendMembers(
-            final String packageName,
-            final String className,
-            final ApplicationMemberSort getMemberSort,
-            final List<String> memberNames) {
-        final Collection<String> memberNamesOf =
-                featureRepository.memberNamesOf(packageName, className, getMemberSort);
-        memberNames.addAll(memberNamesOf);
-    }
-
 
 }