objectClass entries in a Treequel::Schema.
The 'kind' of objectClasses which don't specify a 'kind' explicitly
The objectClass's description
The objectClass's extensions (as a String)
The Array of the objectClass's names
The objectClass's oid
The schema the objectClass belongs to
The OID of the objectClass's superior class (if specified)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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