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



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/treequel/schema/objectclass.rb', line 123

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



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

def desc
  @desc
end

#extensionsObject

The objectClass’s extensions (as a String)



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

def extensions
  @extensions
end

#namesObject (readonly)

The Array of the objectClass’s names



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

def names
  @names
end

#oidObject (readonly)

The objectClass’s oid



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

def oid
  @oid
end

#schemaObject (readonly)

The schema the objectClass belongs to



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

def schema
  @schema
end

#sup_oidObject

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



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

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.



111
112
113
114
115
# File 'lib/treequel/schema/objectclass.rb', line 111

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.



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

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.



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
105
# File 'lib/treequel/schema/objectclass.rb', line 63

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.



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

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



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

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’



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

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.



213
214
215
216
217
218
219
# File 'lib/treequel/schema/objectclass.rb', line 213

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.



200
201
202
203
204
205
206
207
208
# File 'lib/treequel/schema/objectclass.rb', line 200

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.



188
189
190
191
192
193
194
# File 'lib/treequel/schema/objectclass.rb', line 188

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.



175
176
177
178
179
180
181
182
183
# File 'lib/treequel/schema/objectclass.rb', line 175

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.



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

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)


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

def structural?
	return false
end

#supObject

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



279
280
281
282
283
284
285
# File 'lib/treequel/schema/objectclass.rb', line 279

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.



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
259
# File 'lib/treequel/schema/objectclass.rb', line 231

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