Class: Treequel::Schema::ObjectClass

Inherits:
Object
  • Object
show all
Extended by:
Loggability, AttributeDeclarations
Includes:
Constants::Patterns
Defined in:
lib/treequel/schema/objectclass.rb

Overview

objectClass entries in a Treequel::Schema.

Constant Summary collapse

DEFAULT_OBJECTCLASS_KIND =

The ‘kind’ of objectClasses which don’t specify a ‘kind’ explicitly

'STRUCTURAL'

Constants included from Constants::Patterns

Constants::Patterns::ALPHA, Constants::Patterns::AMPERSAND, Constants::Patterns::ASSERTIONVALUE, Constants::Patterns::ASTERISK, Constants::Patterns::ATTRIBUTE_TYPE, Constants::Patterns::ATTRIBUTE_TYPE_AND_VALUE, Constants::Patterns::ATTRIBUTE_VALUE, Constants::Patterns::BASE64_CHAR, Constants::Patterns::BASE64_STRING, Constants::Patterns::COLON, Constants::Patterns::COMMA, Constants::Patterns::DESCR, Constants::Patterns::DIGIT, Constants::Patterns::DISTINGUISHED_NAME, Constants::Patterns::DN_ESCAPED, Constants::Patterns::DOLLAR, Constants::Patterns::DOT, Constants::Patterns::DQUOTE, Constants::Patterns::DSTRING, Constants::Patterns::EQUALS, Constants::Patterns::ESC, Constants::Patterns::ESCAPED, Constants::Patterns::EXCLAMATION, Constants::Patterns::EXTENSIONS, Constants::Patterns::FILL, Constants::Patterns::FOLD, Constants::Patterns::HEX, Constants::Patterns::HEXPAIR, Constants::Patterns::HEXSTRING, Constants::Patterns::HYPHEN, Constants::Patterns::KEYCHAR, Constants::Patterns::KEYSTRING, Constants::Patterns::KIND, Constants::Patterns::LANGLE, Constants::Patterns::LCURLY, Constants::Patterns::LDAP_ATTRIBUTE_DESCRIPTION, Constants::Patterns::LDAP_ATTRIBUTE_TYPE_DESCRIPTION, Constants::Patterns::LDAP_MATCHING_RULE_DESCRIPTION, Constants::Patterns::LDAP_MATCHING_RULE_USE_DESCRIPTION, Constants::Patterns::LDAP_MISORDERED_DESC_OBJECTCLASS_DESCRIPTION, Constants::Patterns::LDAP_MISORDERED_KIND_OBJECTCLASS_DESCRIPTION, Constants::Patterns::LDAP_MISORDERED_SYNTAX_ATTRIBUTE_TYPE_DESCRIPTION, Constants::Patterns::LDAP_OBJECTCLASS_DESCRIPTION, Constants::Patterns::LDAP_SUBSTRING_FILTER, Constants::Patterns::LDAP_SUBSTRING_FILTER_VALUE, Constants::Patterns::LDAP_SYNTAX_DESCRIPTION, Constants::Patterns::LDAP_TRAILING_KIND_OBJECTCLASS_DESCRIPTION, Constants::Patterns::LDAP_UNESCAPE_SQUOTE_ATTRIBUTE_TYPE_DESCRIPTION, Constants::Patterns::LDIF_ATTRIBUTE_DESCRIPTION, Constants::Patterns::LDIF_ATTRIBUTE_TYPE, Constants::Patterns::LDIF_ATTRTYPE_OPTION, Constants::Patterns::LDIF_ATTRTYPE_OPTIONS, Constants::Patterns::LDIF_ATTRVAL_SPEC, Constants::Patterns::LDIF_ATTR_TYPE_CHARS, Constants::Patterns::LDIF_OPT_CHAR, Constants::Patterns::LDIF_SAFE_CHAR, Constants::Patterns::LDIF_SAFE_INIT_CHAR, Constants::Patterns::LDIF_SAFE_STRING, Constants::Patterns::LDIF_VALUE_SPEC, Constants::Patterns::LDIGIT, Constants::Patterns::LEADCHAR, Constants::Patterns::LEADKEYCHAR, Constants::Patterns::LEN, Constants::Patterns::LPAREN, Constants::Patterns::LUTF1, Constants::Patterns::MALFORMED_DSTRING, Constants::Patterns::MALFORMED_QDSTRING, Constants::Patterns::NOIDLEN, Constants::Patterns::NORMAL, Constants::Patterns::NUL, Constants::Patterns::NUMBER, Constants::Patterns::NUMERICOID, Constants::Patterns::OCTET, Constants::Patterns::OID, Constants::Patterns::OIDLIST, Constants::Patterns::OIDS, Constants::Patterns::PAIR, Constants::Patterns::PLUS, Constants::Patterns::QDESCR, Constants::Patterns::QDESCRLIST, Constants::Patterns::QDESCRS, Constants::Patterns::QDSTRING, Constants::Patterns::QDSTRINGLIST, Constants::Patterns::QDSTRINGS, Constants::Patterns::QQ, Constants::Patterns::QS, Constants::Patterns::QUOTED_DESCR, Constants::Patterns::QUOTED_NUMERICOID, Constants::Patterns::QUTF1, Constants::Patterns::QUTF8, Constants::Patterns::RANGLE, Constants::Patterns::RCURLY, Constants::Patterns::RELATIVE_DISTINGUISHED_NAME, Constants::Patterns::RPAREN, Constants::Patterns::SEMI, Constants::Patterns::SEP, Constants::Patterns::SHARP, Constants::Patterns::SP, Constants::Patterns::SPACE, Constants::Patterns::SPECIAL, Constants::Patterns::SQUOTE, Constants::Patterns::STRING, Constants::Patterns::STRINGCHAR, Constants::Patterns::SUTF1, Constants::Patterns::TILDE, Constants::Patterns::TRAILCHAR, Constants::Patterns::TUTF1, Constants::Patterns::UNESCAPED, Constants::Patterns::URI_REF, Constants::Patterns::USAGE, Constants::Patterns::USCORE, Constants::Patterns::UTF0, Constants::Patterns::UTF1, Constants::Patterns::UTF1SUBSET, Constants::Patterns::UTF2, Constants::Patterns::UTF3, Constants::Patterns::UTF4, Constants::Patterns::UTF8, Constants::Patterns::UTFMB, Constants::Patterns::VALUEENCODING, Constants::Patterns::VERTBAR, Constants::Patterns::WSP, Constants::Patterns::XSTRING

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AttributeDeclarations

predicate_attr

Constructor Details

#initialize(schema, oid, names = nil, desc = nil, obsolete = false, sup = nil, must_oids = [], may_oids = [], extensions = nil) ⇒ ObjectClass

Create a new ObjectClass



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# 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

Instance Attribute Details

#descObject

The objectClass’s description



153
154
155
# File 'lib/treequel/schema/objectclass.rb', line 153

def desc
  @desc
end

#extensionsObject

The objectClass’s extensions (as a String)



162
163
164
# File 'lib/treequel/schema/objectclass.rb', line 162

def extensions
  @extensions
end

#namesObject (readonly)

The Array of the objectClass’s names



150
151
152
# File 'lib/treequel/schema/objectclass.rb', line 150

def names
  @names
end

#oidObject (readonly)

The objectClass’s oid



147
148
149
# File 'lib/treequel/schema/objectclass.rb', line 147

def oid
  @oid
end

#schemaObject (readonly)

The schema the objectClass belongs to



144
145
146
# File 'lib/treequel/schema/objectclass.rb', line 144

def schema
  @schema
end

#sup_oidObject

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



159
160
161
# File 'lib/treequel/schema/objectclass.rb', line 159

def sup_oid
  @sup_oid
end

Class Method Details

.handle_malformed_parse(message, oc_desc) ⇒ Object

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.



110
111
112
113
114
# 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

.inherited(subclass) ⇒ Object

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



55
56
57
# File 'lib/treequel/schema/objectclass.rb', line 55

def self::inherited( subclass )
	subclass.instance_eval { public_class_method :new }
end

.parse(schema, description) ⇒ Object

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



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# 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

Instance Method Details

#ancestorsObject

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



289
290
291
292
293
294
295
296
297
# File 'lib/treequel/schema/objectclass.rb', line 289

def ancestors
	rval = [ self ]

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

	return rval
end

#inspectObject

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



262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/treequel/schema/objectclass.rb', line 262

def inspect
	return %{#<%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

#kindObject

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



302
303
304
# File 'lib/treequel/schema/objectclass.rb', line 302

def kind
	return Treequel::Schema::OBJECTCLASS_TYPES.invert[ self.class ]
end

#may(include_sup = true) ⇒ Object

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



212
213
214
215
216
217
218
# 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

#may_oids(include_sup = true) ⇒ Object

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.



199
200
201
202
203
204
205
206
207
# 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

#must(include_sup = true) ⇒ Object

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



187
188
189
190
191
192
193
# 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

#must_oids(include_sup = true) ⇒ Object

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.



174
175
176
177
178
179
180
181
182
# 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

#nameObject

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



166
167
168
# File 'lib/treequel/schema/objectclass.rb', line 166

def name
	return self.names.first
end

#structural?Boolean

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

Returns:

  • (Boolean)


223
224
225
# File 'lib/treequel/schema/objectclass.rb', line 223

def structural?
	return false
end

#supObject

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



278
279
280
281
282
283
284
# 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

#to_sObject

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



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# 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