Treequel::Schema::

ObjectClass

class
Superclass
Object
Included Modules
Treequel::Constants::Patterns
Extended With
Loggability
Treequel::AttributeDeclarations

objectClass entries in a Treequel::Schema.

Constants

DEFAULT_OBJECTCLASS_KIND

The 'kind' of objectClasses which don't specify a 'kind' explicitly

Attributes

desc[RW]

The objectClass's description

extensions[RW]

The objectClass's extensions (as a String)

names[R]

The Array of the objectClass's names

oid[R]

The objectClass's oid

schema[R]

The schema the objectClass belongs to

sup_oid[RW]

The OID of the objectClass's superior class (if specified)

Public Class Methods

anchor
handle_malformed_parse( message, oc_desc )

Handle the parse of an objectClass that matches one of the non-standard objectClass definitions found in several RFCs. If Treequel::Schema.strict_parse_mode? is true, this method will raise an exception.

# File lib/treequel/schema/objectclass.rb, line 110
def self::handle_malformed_parse( message, oc_desc )
        raise Treequel::ParseError, "Malformed objectClass: %s: %p" % [ message, oc_desc ] if
                Treequel::Schema.strict_parse_mode?
        Treequel.log.info "Working around malformed objectClass: %s: %p" % [ message, oc_desc ]
end
anchor
inherited( subclass )

Inheritance callback: Make the constructor method of all inheriting classes public.

# File lib/treequel/schema/objectclass.rb, line 55
def self::inherited( subclass )
        subclass.instance_eval { public_class_method :new }
end
anchor
new( schema, oid, names=nil, desc=nil, obsolete=false, sup=nil, must_oids=[], may_oids=[], extensions=nil )

Create a new ObjectClass

# File lib/treequel/schema/objectclass.rb, line 122
def initialize( schema, oid, names=nil, desc=nil, obsolete=false, sup=nil, must_oids=[],
                may_oids=[], extensions=nil )
        @schema     = schema

        @oid        = oid
        @names      = names
        @desc       = desc
        @obsolete   = obsolete ? true : false
        @sup_oid    = sup
        @must_oids  = must_oids
        @may_oids   = may_oids
        @extensions = extensions

        super()
end
anchor
parse( schema, description )

Parse an ObjectClass entry from a RFC4512-format objectClass description from a schema.

# File lib/treequel/schema/objectclass.rb, line 62
def self::parse( schema, description )
        oid, names, desc, obsolete, sup, kind, must, may, extensions = nil

        # :FIXME: Change this to some sort of strategy that extracts the pieces from the
        # description and checks to be sure everything was consumed instead of depending
        # on the RFC's BNF. It appears people expect to be able to arbitrarily reorder
        # them, and making a different Regexp for each exception isn't going to work
        # long-term.
        case description.gsub( /[\n\t]+/, ' ' ).squeeze( ' ' )
        when LDAP_OBJECTCLASS_DESCRIPTION
                oid, names, desc, obsolete, sup, kind, must, may, extensions = $~.captures
        when LDAP_MISORDERED_KIND_OBJECTCLASS_DESCRIPTION
                oid, names, desc, obsolete, kind, sup, must, may, extensions = $~.captures
                self.handle_malformed_parse( "transposed KIND (#{kind}) and SUP (#{sup})",
                                              description )
        when LDAP_TRAILING_KIND_OBJECTCLASS_DESCRIPTION
                oid, names, desc, obsolete, sup, must, may, kind, extensions = $~.captures
                self.handle_malformed_parse( "misordered KIND (#{kind})", description )
        when LDAP_MISORDERED_DESC_OBJECTCLASS_DESCRIPTION
                oid, names, obsolete, sup, kind, desc, must, may, extensions = $~.captures
                self.handle_malformed_parse( "misordered DESC (#{desc})", description )
        else
                raise Treequel::ParseError, "failed to parse objectClass from %p" % [ description ]
        end

        # Normalize the attributes
        must_oids  = Treequel::Schema.parse_oids( must )
        may_oids   = Treequel::Schema.parse_oids( may )
        names      = Treequel::Schema.parse_names( names )
        desc       = Treequel::Schema.unquote_desc( desc )
        extensions = extensions.strip

        # Default the 'kind' attribute
        kind ||= DEFAULT_OBJECTCLASS_KIND

        # Find the appropriate concrete class to instantiate
        concrete_class = Treequel::Schema::OBJECTCLASS_TYPES[ kind ] or
                raise Treequel::Error, "no such objectClass type %p: expected one of: %p" %
                        [ kind, Treequel::Schema::OBJECTCLASS_TYPES.keys ]

        return concrete_class.new( schema, oid, names, desc, obsolete, sup,
                                   must_oids, may_oids, extensions )
end

Public Instance Methods

anchor
ancestors()

Return the SUP chain for the receiver up to 'top', including the receiver itself, as an Array of Treequel::Schema::ObjectClass objects.

# File lib/treequel/schema/objectclass.rb, line 289
def ancestors
        rval = [ self ]

        if parent = self.sup
                rval += parent.ancestors
        end

        return rval
end
anchor
inspect()

Return a human-readable representation of the object suitable for debugging

# File lib/treequel/schema/objectclass.rb, line 262
def inspect
        return %Q{#<%s:0x%0x %s(%s) < %s "%s" MUST: %p, MAY: %p>} % [
                self.class.name,
                self.object_id / 2,
                self.name,
                self.oid,
                self.sup_oid,
                self.desc,
                self.must_oids,
                self.may_oids,
        ]
end
anchor
kind()

Return the string that represents the kind of objectClass the receiver represents. It will be one of: 'ABSTRACT', 'STRUCTURAL', 'AUXILIARY'

# File lib/treequel/schema/objectclass.rb, line 302
def kind
        return Treequel::Schema::OBJECTCLASS_TYPES.invert[ self.class ]
end
anchor
may( include_sup=true )

Return Treequel::Schema::AttributeType objects for each of the objectClass's MAY attributes.

# File lib/treequel/schema/objectclass.rb, line 212
def may( include_sup=true )
        self.may_oids( include_sup ).collect do |oid|
                self.log.warn "No attribute type for OID %p (case bug?)" % [ oid ] unless
                        self.schema.attribute_types.key?( oid )
                self.schema.attribute_types[oid]
        end.compact
end
anchor
may_oids( include_sup=true )

Return the objectClass's MAY OIDs as Symbols (for symbolic OIDs) or Strings (for dotted-numeric OIDs). If include_sup is true, include MAY OIDs inherited from the objectClass's SUP, if it has one.

# File lib/treequel/schema/objectclass.rb, line 199
def may_oids( include_sup=true )
        oids = @may_oids.dup

        if include_sup && superclass = self.sup
                oids.unshift( *superclass.may_oids )
        end

        return oids.flatten
end
anchor
must( include_sup=true )

Return Treequel::Schema::AttributeType objects for each of the objectClass's MUST attributes.

# File lib/treequel/schema/objectclass.rb, line 187
def must( include_sup=true )
        self.must_oids( include_sup ).collect do |oid|
                self.log.warn "No attribute type for OID %p (case bug?)" % [ oid ] unless
                        self.schema.attribute_types.key?( oid )
                self.schema.attribute_types[oid]
        end.compact
end
anchor
must_oids( include_sup=true )

Return the objectClass's MUST OIDs as Symbols (for symbolic OIDs) or Strings (for dotted-numeric OIDs). If include_sup is true, include MUST OIDs inherited from the objectClass's SUP, if it has one.

# File lib/treequel/schema/objectclass.rb, line 174
def must_oids( include_sup=true )
        oids = @must_oids.dup

        if include_sup && superclass = self.sup
                oids.unshift( *superclass.must_oids )
        end

        return oids.flatten
end
anchor
name()

Return the first of the objectClass's names, if it has any, or nil.

# File lib/treequel/schema/objectclass.rb, line 166
def name
        return self.names.first
end
anchor
structural?()

Returns true if this objectClass is STRUCTURAL. Defaults to false and then overridden in StructuralObjectClass.

# File lib/treequel/schema/objectclass.rb, line 223
def structural?
        return false
end
anchor
sup()

Return the ObjectClass for the receiver's SUP. If this is called on 'top', returns nil.

# File lib/treequel/schema/objectclass.rb, line 278
def sup
        unless name = self.sup_oid
                return nil if self.oid == Treequel::Constants::OIDS::TOP_OBJECTCLASS
                return self.schema.object_classes[ :top ]
        end
        return self.schema.object_classes[ name.to_sym ]
end
anchor
to_s()

Returns the objectClass as a String, which is the RFC4512-style schema description.

# File lib/treequel/schema/objectclass.rb, line 230
    def to_s
            # ObjectClassDescription = LPAREN WSP
        #     numericoid                 ; object identifier
        #     [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
        #     [ SP "DESC" SP qdstring ]  ; description
        #     [ SP "OBSOLETE" ]          ; not active
        #     [ SP "SUP" SP oids ]       ; superior object classes
        #     [ SP kind ]                ; kind of class
        #     [ SP "MUST" SP oids ]      ; attribute types
        #     [ SP "MAY" SP oids ]       ; attribute types
        #     extensions WSP RPAREN
#
        # kind = "ABSTRACT" / "STRUCTURAL" / "AUXILIARY"

            parts = [ self.oid ]

            parts << "NAME %s" % Treequel::Schema.qdescrs( self.names ) unless self.names.empty?
            parts << "DESC %s" % [ Treequel::Schema.qdstring(self.desc) ] if self.desc
            parts << "OBSOLETE" if self.obsolete?
            parts << "SUP %s" % [ Treequel::Schema.oids(self.sup_oid) ] if self.sup_oid
            parts << self.kind
            parts << "MUST %s" % [ Treequel::Schema.oids(self.must_oids(false)) ] unless
                    self.must_oids(false).empty?
            parts << "MAY %s" % [ Treequel::Schema.oids(self.may_oids(false)) ] unless
                    self.may_oids(false).empty?
            parts << self.extensions.strip unless self.extensions.empty?

            return "( %s )" % [ parts.join(' ') ]
    end