def _get_object_properties_schema(object_schema, object_keys=None):
        """
        Create a schema for an object property using all of: properties,
        patternProperties, and additionalProperties.

        This 'flattens' properties, patternProperties, and additionalProperties
        so that we can handle patternProperties and additionalProperties
        as if they were defined in properties.
        So, every key in object_keys will be assigned a schema
        from properties, patternProperties, or additionalProperties.

        NOTE: order of precedence: properties, patternProperties, additionalProperties
        So, the additionalProperties schema is only used for keys that are not in
        properties and that do not match any of the patterns in patternProperties.
        And, patternProperties schemas only apply to keys missing from properties.

        :rtype: ``dict``
        """
        # preserve the order in object_keys
        flattened_properties_schema = {key: {} for key in object_keys}

        # properties takes precedence over patternProperties and additionalProperties
        properties_schema = object_schema.get("properties", {})
        flattened_properties_schema.update(properties_schema)

        # extra_keys has keys that may use patternProperties or additionalProperties
        # we remove keys when they have been assigned a schema
        extra_keys = set(object_keys) - set(properties_schema.keys())

        if not extra_keys:
            # nothing to check. Don't look at patternProperties or additionalProperties.
            return flattened_properties_schema

        # match each key against patternPropetties
        pattern_properties = object_schema.get("patternProperties", {})
        # patternProperties should be a dict if defined
        if pattern_properties and isinstance(pattern_properties, dict):
            # we need to match all extra_keys against all patterns
            # and then compose the per-property schema from all
            # the matched patterns' properties.
            pattern_properties = {
                re.compile(raw_pattern): pattern_schema
                for raw_pattern, pattern_schema in pattern_properties.items()
            }
            for key in list(extra_keys):
                key_schemas = []
                for pattern, pattern_schema in pattern_properties.items():
                    if pattern.search(key):
                        key_schemas.append(pattern_schema)
                if key_schemas:
                    # This naive schema composition approximates allOf.
                    # We can improve this later if someone provides examples that need
                    # a better allOf schema implementation for patternProperties.
                    composed_schema = {}
                    for schema in key_schemas:
                        composed_schema.update(schema)
                    # update matched key
                    flattened_properties_schema[key] = composed_schema
                    # don't overwrite matched key's schema with additionalProperties
                    extra_keys.remove(key)

            if not extra_keys:
                # nothing else to check. Don't look at additionalProperties.
                return flattened_properties_schema

        # fill in any remaining keys with additionalProperties
        additional_properties = object_schema.get("additionalProperties", {})
        # additionalProperties can be a boolean or a dict
        if additional_properties and isinstance(additional_properties, dict):
            # ensure that these keys are present in the object
            for key in extra_keys:
                flattened_properties_schema[key] = additional_properties

        return flattened_properties_schema

        Create a schema for an object property using all of: properties,
        patternProperties, and additionalProperties.

        This 'flattens' properties, patternProperties, and additionalProperties
        so that we can handle patternProperties and additionalProperties
        as if they were defined in properties.
        So, every key in object_keys will be assigned a schema
        from properties, patternProperties, or additionalProperties.

        NOTE: order of precedence: properties, patternProperties, additionalProperties
        So, the additionalProperties schema is only used for keys that are not in
        properties and that do not match any of the patterns in patternProperties.
        And, patternProperties schemas only apply to keys missing from properties.

        :rtype: ``dict``
        
st2common/st2common/util/config_loader.py