#include "XmlSchemaElement.h"
#include "XmlSchema.h"
#include "NSString+XML.h"
#include "common.h"
@implementation XmlSchemaElement
#if !LIB_FOUNDATION_BOEHM_GC
- (void)dealloc {
RELEASE(self->block);
RELEASE(self->defValue);
RELEASE(self->fixed);
RELEASE(self->form);
RELEASE(self->maxOccurs);
RELEASE(self->minOccurs);
RELEASE(self->ref);
RELEASE(self->substitutionGroup);
RELEASE(self->type);
RELEASE(self->contentType);
[super dealloc];
}
#endif
/* attributes */
- (BOOL)abstract {
return self->abstract;
}
- (NSString *)block {
return self->block;
}
- (NSString *)default {
return self->defValue;
}
- (NSString *)fixed {
return self->fixed;
}
- (NSString *)form {
return self->form;
}
- (NSString *)maxOccurs {
return self->maxOccurs;
}
- (NSString *)minOccurs {
return self->minOccurs;
}
- (BOOL)nillable {
return self->nillable;
}
- (NSString *)ref {
return self->ref;
}
- (NSString *)substitutionGroup {
return self->substitutionGroup;
}
- (NSString *)type {
return self->type;
}
- (NSString *)typeValue {
return (self->type) ? [self->type valueFromQName] : self->name;
}
/* accessors */
- (BOOL)isSimpleType {
if (self->contentType == nil) return YES;
return [self->contentType isSimpleType];
}
- (BOOL)isScalar {
if ([self->maxOccurs intValue] == 1)
return YES;
else
return NO;
}
- (NSArray *)elementNames {
if ([self isSimpleType])
return [NSArray array];
else {
return [[self->contentType content] elementNames];
}
}
- (XmlSchemaElement *)elementWithName:(NSString *)_name {
return [[self->contentType content] elementWithName:_name];
}
- (NSArray *)attributeNames {
if ([self isSimpleType])
return [NSArray array];
else {
return [self->contentType attributeNames];
}
}
- (XmlSchemaAttribute *)attributeWithName:(NSString *)_name {
return [self->contentType attributeWithName:_name];
}
- (void)setContentType:(XmlSchemaType *)_contentType {
ASSIGN(self->contentType, _contentType);
}
- (XmlSchemaType *)contentType {
return self->contentType;
}
- (XmlSchemaContent *)content {
return [self-> contentType content];
}
- (NSString *)description {
NSMutableString *str = [NSMutableString stringWithCapacity:128];
[str appendString:@"type attr:@"type" toString:str];
[self append:self->block attr:@"block" toString:str];
[self append:self->defValue attr:@"defValue" toString:str];
[self append:[self final] attr:@"final" toString:str];
[self append:self->fixed attr:@"fixed" toString:str];
[self append:[self id] attr:@"id" toString:str];
[self append:self->maxOccurs attr:@"maxOccurs" toString:str];
[self append:self->minOccurs attr:@"minOccurs" toString:str];
[self append:self->ref attr:@"ref" toString:str];
[self append:self->substitutionGroup attr:@"substitutionGroup" toString:str];
[self append:(self->abstract) ? @"true" : @"false"
attr:@"abstract" toString:str];
[self append:(self->nillable) ? @"true" : @"false"
attr:@"nillable" toString:str];
[str appendString:@">"];
[str appendString:[self->contentType description]];
[str appendString:@"\n"];
return str;
}
@end /* XmlSchemaElement */
@implementation XmlSchemaElement(XmlSchemaSaxBuilder)
static NSSet *Valid_element_ContentTags = nil;
+ (void)initialize {
if (Valid_element_ContentTags == nil) {
Valid_element_ContentTags = [[NSSet alloc] initWithObjects:
@"simpleType",
@"complexType",
@"unique",
@"key",
@"keyref",
nil];
}
}
- (id)initWithAttributes:(id)_attrs
namespace:(NSString *)_namespace
namespaces:(NSDictionary *)_ns {
if ((self = [super initWithAttributes:_attrs
namespace:_namespace
namespaces:_ns])) {
self->block = [[_attrs valueForRawName:@"block"] copy];
self->defValue = [[_attrs valueForRawName:@"default"] copy];
self->fixed = [[_attrs valueForRawName:@"fixed"] copy];
self->form = [[_attrs valueForRawName:@"form"] copy];
self->maxOccurs = [[_attrs valueForRawName:@"maxOccurs"] copy];
self->minOccurs = [[_attrs valueForRawName:@"minOccurs"] copy];
self->ref = [self copy:@"ref" attrs:_attrs ns:_ns];
self->type = [self copy:@"type" attrs:_attrs ns:_ns];
self->substitutionGroup = [self copy:@"substitutionGroup"
attrs:_attrs ns:_ns];
if (self->minOccurs == nil) ASSIGN(self->minOccurs, @"1");
if (self->maxOccurs == nil) ASSIGN(self->maxOccurs, @"1");
if ([self->minOccurs intValue] == 0)
ASSIGN(self->maxOccurs, @"0");
if ([self->maxOccurs intValue] == 0)
ASSIGN(self->maxOccurs, @"unbounded");
if ([[_attrs valueForRawName:@"abstract"] isEqualToString:@"true"])
self->abstract = YES;
if ([[_attrs valueForRawName:@"nillable"] isEqualToString:@"true"])
self->nillable = YES;
#if 0
NSAssert1(self->name, @"XmlSchemaElement: no name set (%@)", self);
NSAssert1((self->ref == nil || self->type == nil),
@"XmlSchemaElement: either ref AND type has to be set (%@)", self);
#endif
}
return self;
}
/*
Schema Representation Constraint: Element Declaration Representation OK
In addition to the conditions imposed on element information items by the schema for schemas: all of the following must be true:
1 default and fixed must not both be present.
2 If the item's parent is not , then all of the following must be true:
2.1 One of ref or name must be present, but not both.
2.2 If ref is present, then all of , , , , , nillable, default, fixed, form, block and type must be absent, i.e. only minOccurs, maxOccurs, id are allowed in addition to ref, along with .
3 type and either or are mutually exclusive.
4 The corresponding particle and/or element declarations must satisfy the conditions set out in Constraints on Element Declaration Schema Components (§3.3.6) and Constraints on Particle Schema Components (§3.9.6).
finding the type:
if (complexType or simpleType tag) -> found
else if (type-attribute is present) -> found
else if (substitutionGroup-attribute) ->found
else 'ur-type' definition.
*/
- (int)checkConstraints:(XmlSchema *)_schema {
if (self->defValue && self->fixed)
return 1; // element: default and fixed attr may not both be present.
if (![[_schema elementWithName:self->name] isEqual:self]) { //toDo:-isEqual:
if (self->ref) {
if ((self->name && self->ref) || (!self->name && !self->ref)) {
return 2;
/*
elememt: One of ref or name must be present, but not both.
(if items parent is not
*/
}
// not allowed: , , , ,
if (self->nillable || self->defValue || self->fixed || self->form ||
self->block || self->type) {
return 3;
}
if (self->contentType)
return 4;
}
}
return 0;
}
- (void)prepareWithSchema:(XmlSchema *)_schema {
XmlSchema *mySchema;
[super prepareWithSchema:_schema];
if (self->ref) {
XmlSchemaElement *elem;
NSString *val = [self->ref valueFromQName];
NSString *uri = [self->ref uriFromQName];
if (uri == nil || [uri isEqualToString:[_schema targetNamespace]])
mySchema = _schema;
else
mySchema = [XmlSchema schemaForNamespace:uri];
elem = [mySchema elementWithName:val];
[self _readFromElement:elem];
}
else if (self->contentType != nil) {
[self->contentType prepareWithSchema:_schema];
}
else if (self->type) {
NSString *val = [self->type valueFromQName];
NSString *uri = [self->type uriFromQName];
if (uri == nil || [uri isEqualToString:[_schema targetNamespace]])
mySchema = _schema;
else
mySchema = [XmlSchema schemaForNamespace:uri];
self->contentType = [mySchema typeWithName:val]; // ToDo: Ref!!!
RETAIN(self->contentType);
}
else if (self->substitutionGroup) {
// ToDo: content type muss noch gesetzt werden
}
else {
// ToDo: 'ur-type' definition ???
}
}
- (BOOL)isTagNameAccepted:(NSString *)_tagName {
if ([super isTagNameAccepted:_tagName])
return YES;
else
return [Valid_element_ContentTags containsObject:_tagName];
}
- (BOOL)addTag:(XmlSchemaTag *)_tag {
if ([Valid_element_ContentTags containsObject:[_tag tagName]]) {
[self setContentType:(XmlSchemaType *)_tag];
return YES;
}
return [super addTag:_tag];
}
- (NSString *)tagName {
return @"element";
}
@end /* XmlSchemaElement(XmlSchemaSaxBuilder) */
@implementation XmlSchemaElement(PrivateMethods)
- (void)_readFromElement:(XmlSchemaElement *)_element {
RELEASE(self->name);
RELEASE(self->defValue);
RELEASE(self->type);
self->name = [[_element name] copy];
self->type = [[_element type] copy];
self->defValue = [[_element default] copy];
[self setContentType:[_element contentType]];
}
@end