code: private static Key key(Resource resource, Object... furtherKeyElements) {
          Key key;
          final Key furtherElementsKey = furtherKeyElements == null ? null : new Key(furtherKeyElements);
          Node node = resource.adaptTo(Node.class);
          if (node != null) {
              try {
                  key = new Key(
                          resource.getResourceType(),
                          resource.getResourceSuperType(),
                          getPrimaryType(node),
                          geMixinTypes(node),
                          furtherElementsKey);
              } catch (RepositoryException e) {
                  throw new RuntimeException("Unable to retrieve the primary type of " + resource + ".", e);
              }
          } else {
              key = new Key(resource.getResourceType(), furtherElementsKey);
          }
          return key;
      }
docs: Generate a {@link Key} representing both the
  {@link org.apache.sling.api.resource.Resource#getResourceType() sling resource type},
  {@link javax.jcr.Node#getPrimaryNodeType() primary node type} and the {@link Node#getMixinNodeTypes() mixin types}
  of the resource, if any. Rationale: Resources may have the same <code>sling:resourceType</code>, but different primary or mixin types,
  thus potentially producing different results when mapped. The cache must thus use these
  types as a key for cached adaptation results.<br />
  
  @param resource           must not be <code>null</code>.
  @param furtherKeyElements can be <code>null</code>
  @return never <code>null</code>.