@Override
  public CompositeRefinedObjectClassDefinition determineCompositeObjectClassDefinition(
      QName structuralObjectClassQName, ShadowKindType kind, String intent) {
    RefinedObjectClassDefinition structuralObjectClassDefinition = null;
    Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions;
    if (kind != null) {
      structuralObjectClassDefinition = getRefinedDefinition(kind, intent);
    }
    if (structuralObjectClassDefinition == null) {
      // Fallback to objectclass only
      if (structuralObjectClassQName == null) {
        throw new IllegalArgumentException("No kind nor objectclass defined");
      }
      structuralObjectClassDefinition = getRefinedDefinition(structuralObjectClassQName);
    }

    if (structuralObjectClassDefinition == null) {
      return null;
    }

    auxiliaryObjectClassDefinitions =
        structuralObjectClassDefinition.getAuxiliaryObjectClassDefinitions();

    return new CompositeRefinedObjectClassDefinitionImpl(
        structuralObjectClassDefinition, auxiliaryObjectClassDefinitions);
  }
 @Override
 public List<? extends RefinedObjectClassDefinition> getRefinedDefinitions(ShadowKindType kind) {
   List<RefinedObjectClassDefinition> rv = new ArrayList<>();
   for (RefinedObjectClassDefinition def : getRefinedDefinitions()) {
     if (MiscSchemaUtil.matchesKind(kind, def.getKind())) {
       rv.add(def);
     }
   }
   return rv;
 }
 @Override
 public RefinedObjectClassDefinition getRefinedDefinition(
     ShadowKindType kind, Collection<String> intents) throws SchemaException {
   RefinedObjectClassDefinition found = null;
   for (RefinedObjectClassDefinition acctDef : getRefinedDefinitions(kind)) {
     RefinedObjectClassDefinition foundCurrent = null;
     if (intents == null || intents.isEmpty()) {
       if (acctDef.isDefault()) {
         foundCurrent = acctDef;
       }
     } else {
       if (intents.contains(acctDef.getIntent())) {
         foundCurrent = acctDef;
       }
     }
     if (foundCurrent != null) {
       if (found != null) {
         if (!QNameUtil.match(found.getTypeName(), foundCurrent.getTypeName())) {
           throw new SchemaException(
               "More than one ObjectClass found for kind "
                   + kind
                   + ", intents: "
                   + intents
                   + ": "
                   + found.getTypeName()
                   + ", "
                   + foundCurrent.getTypeName());
         }
       } else {
         found = foundCurrent;
       }
     }
   }
   return found;
 }
 @Override
 public RefinedObjectClassDefinition getRefinedDefinition(ShadowKindType kind, String intent) {
   for (RefinedObjectClassDefinition acctDef : getRefinedDefinitions(kind)) {
     if (intent == null && acctDef.isDefault()) {
       return acctDef;
     }
     if (acctDef.getIntent() != null && acctDef.getIntent().equals(intent)) {
       return acctDef;
     }
     if (acctDef.getIntent() == null && intent == null) {
       return acctDef;
     }
   }
   return null;
 }
 @Override
 public RefinedObjectClassDefinition getRefinedDefinition(QName objectClassName) {
   for (RefinedObjectClassDefinition def : getRefinedDefinitions()) {
     if (def.isDefault() && (QNameUtil.match(def.getTypeName(), objectClassName))) {
       return def;
     }
   }
   // No default for this object class, so just use the first one.
   // This is not strictly correct .. but it is a "compatible bug" :-)
   // TODO: remove this in next major revision
   for (RefinedObjectClassDefinition def : getRefinedDefinitions()) {
     if ((QNameUtil.match(def.getTypeName(), objectClassName))) {
       return def;
     }
   }
   return null;
 }
 @Override
 public CompositeRefinedObjectClassDefinition determineCompositeObjectClassDefinition(
     ResourceShadowDiscriminator discriminator) {
   if (discriminator.getKind() == null && discriminator.getObjectClass() == null) {
     return null;
   }
   RefinedObjectClassDefinition structuralObjectClassDefinition;
   if (discriminator.getKind() == null && discriminator.getObjectClass() != null) {
     structuralObjectClassDefinition = getRefinedDefinition(discriminator.getObjectClass());
   } else {
     structuralObjectClassDefinition =
         getRefinedDefinition(discriminator.getKind(), discriminator.getIntent());
   }
   if (structuralObjectClassDefinition == null) {
     return null;
   }
   Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions =
       structuralObjectClassDefinition.getAuxiliaryObjectClassDefinitions();
   return new CompositeRefinedObjectClassDefinitionImpl(
       structuralObjectClassDefinition, auxiliaryObjectClassDefinitions);
 }
  private static void parseObjectTypesFromSchema(
      RefinedResourceSchemaImpl rSchema,
      ResourceType resourceType,
      PrismContext prismContext,
      String contextDescription)
      throws SchemaException {

    RefinedObjectClassDefinition rAccountDefDefault = null;
    for (ObjectClassComplexTypeDefinition objectClassDef :
        rSchema.getOriginalResourceSchema().getObjectClassDefinitions()) {
      QName objectClassname = objectClassDef.getTypeName();
      if (rSchema.getRefinedDefinition(objectClassname) != null) {
        continue;
      }
      RefinedObjectClassDefinition rOcDef =
          RefinedObjectClassDefinitionImpl.parseFromSchema(
              objectClassDef,
              resourceType,
              rSchema,
              prismContext,
              "object class " + objectClassname + ", in " + contextDescription);

      if (objectClassDef.getKind() == ShadowKindType.ACCOUNT && rOcDef.isDefault()) {
        if (rAccountDefDefault == null) {
          rAccountDefDefault = rOcDef;
        } else {
          throw new SchemaException(
              "More than one default account definitions ("
                  + rAccountDefDefault
                  + ", "
                  + rOcDef
                  + ") in "
                  + contextDescription);
        }
      }

      rSchema.add(rOcDef);
    }
  }
 @Override
 public RefinedObjectClassDefinition findRefinedDefinitionByObjectClassQName(
     ShadowKindType kind, QName objectClass) {
   if (objectClass == null) {
     return getDefaultRefinedDefinition(kind);
   }
   for (RefinedObjectClassDefinition acctDef : getRefinedDefinitions(kind)) {
     if (acctDef.isDefault()
         && QNameUtil.match(acctDef.getObjectClassDefinition().getTypeName(), objectClass)) {
       return acctDef;
     }
   }
   // No default for this object class, so just use the first one.
   // This is not strictly correct .. but it is a "compatible bug" :-)
   // TODO: remove this in next major revision
   for (RefinedObjectClassDefinition acctDef : getRefinedDefinitions(kind)) {
     if (QNameUtil.match(acctDef.getObjectClassDefinition().getTypeName(), objectClass)) {
       return acctDef;
     }
   }
   return null;
 }
  private static void parseObjectTypeDefsFromSchemaHandling(
      RefinedResourceSchemaImpl rSchema,
      ResourceType resourceType,
      SchemaHandlingType schemaHandling,
      Collection<ResourceObjectTypeDefinitionType> resourceObjectTypeDefs,
      ShadowKindType impliedKind,
      PrismContext prismContext,
      String contextDescription)
      throws SchemaException {

    if (resourceObjectTypeDefs == null) {
      return;
    }

    Map<ShadowKindType, RefinedObjectClassDefinition> defaults = new HashMap<>();

    for (ResourceObjectTypeDefinitionType accountTypeDefType : resourceObjectTypeDefs) {
      RefinedObjectClassDefinition rOcDef =
          RefinedObjectClassDefinitionImpl.parse(
              accountTypeDefType,
              resourceType,
              rSchema,
              impliedKind,
              prismContext,
              contextDescription);

      if (rOcDef.isDefault()) {
        if (defaults.containsKey(rOcDef.getKind())) {
          throw new SchemaException(
              "More than one default "
                  + rOcDef.getKind()
                  + " definitions ("
                  + defaults.get(rOcDef.getKind())
                  + ", "
                  + rOcDef
                  + ") in "
                  + contextDescription);
        } else {
          defaults.put(rOcDef.getKind(), rOcDef);
        }
      }

      rSchema.add(rOcDef);
    }
  }