我现在已经隔离了我之前也询问过的Redland RDF库的一个问题。所以我仍然想知道:是什么导致以下测试用例失败?
基本上应该发生以下情况:我正在构建两个 RDF 模型,每个模型都包含一个事件 ID。我使用这些事件 ID 作为字典(哈希表)的键。由于 RDF 模型是 C 结构,我将它们包装在一个 Objective C 类中以获得可以存储在字典中的东西。现在,当我尝试通过这些不同的键从字典中检索两个 RDF 模型时,我总是会返回相同的RDF 模型。RDF 模型的指针值是不同的,但所有包含的 RDF 节点显然是相同的。我错过了什么?(顺便说一句,我很确定问题不是所有混淆的产物:)
//
// RedlandRdfStandaloneTests.h
//
#import <SenTestingKit/SenTestingKit.h>
@interface RedlandRdfStandaloneTests : SenTestCase
@end
//
// RedlandRdfStandaloneTests.m
//
#import "librdf.h"
#import "RdfModelWrapper.h"
#import "RedlandRdfStandaloneTests.h"
// namespace URIs
#define OBFUSCATED6_NAMESPACE @"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED7#"
// datatype properties
#define OBFUSCATED6_EVENT_ID_LOCAL_NAME @"eventId"
// individuals
#define OBFUSCATED6_CALENDAR_EVENT_LOCAL_NAME @"CalendarEvent"
#define IDENTIFIER_1 @"dc4bc97ugu7kl5hoh2spmanob4"
#define IDENTIFIER_2 @"cbd3mghbgas8juuh4l88rt04ec"
@interface RedlandRdfStandaloneTests ()
@property (assign, readonly) librdf_world *rdfWorld;
@property (assign, readonly) librdf_storage *rdfStorage;
@property (assign, readonly) librdf_node *rdfTypeProperty;
@property (assign, readonly) librdf_uri *obfuscated8NamespaceUri;
@property (assign, readonly) librdf_node *obfuscated8EventIdProperty;
@property (assign, readonly) librdf_node *obfuscated8CalendarEventIndividual;
@property (assign, readonly) librdf_parser *rdfParser;
@property (assign, readonly) librdf_uri *baseUri;
@property (strong, readonly) NSString *rdfModel1AsString;
@property (strong, readonly) NSString *rdfModel2AsString;
@end
@implementation RedlandRdfStandaloneTests
- (void)test
{
NSMutableDictionary *identifiersToRdfModelWrappers = [NSMutableDictionary dictionary];
librdf_model *rdfModel;
{
rdfModel = librdf_new_model(_rdfWorld, _rdfStorage, NULL);
librdf_parser_parse_string_into_model(_rdfParser, (const unsigned char *)_rdfModel1AsString.UTF8String, _baseUri, rdfModel);
RdfModelWrapper *rdfModelWrapper = [[RdfModelWrapper alloc] initWithRdfModel:rdfModel];
[identifiersToRdfModelWrappers setObject:rdfModelWrapper forKey:IDENTIFIER_1];
[self writeModel:rdfModel withRdfWorld:_rdfWorld]; // #1: ok -- same as _rdfModel1AsString with eventId same as IDENTIFIER_1
}
{
rdfModel = librdf_new_model(_rdfWorld, _rdfStorage, NULL);
librdf_parser_parse_string_into_model(_rdfParser, (const unsigned char *)_rdfModel2AsString.UTF8String, _baseUri, rdfModel);
RdfModelWrapper *rdfModelWrapper = [[RdfModelWrapper alloc] initWithRdfModel:rdfModel];
[identifiersToRdfModelWrappers setObject:rdfModelWrapper forKey:IDENTIFIER_2];
[self writeModel:rdfModel withRdfWorld:_rdfWorld]; // #2: ok -- same as _rdfModel2AsString with eventId same as IDENTIFIER_2
}
{
RdfModelWrapper *rdfModelWrapper = [identifiersToRdfModelWrappers objectForKey:IDENTIFIER_1];
rdfModel = rdfModelWrapper.rdfModel;
librdf_node *eventResource = librdf_model_get_source(rdfModel, _rdfTypeProperty, _obfuscated8CalendarEventIndividual);
librdf_node *eventIdLiteral = librdf_model_get_target(rdfModel, eventResource, _obfuscated8EventIdProperty);
NSString *eventId = [NSString stringWithCString:librdf_node_get_literal_value_as_latin1(eventIdLiteral) encoding:NSISOLatin1StringEncoding];
[self writeModel:rdfModel withRdfWorld:_rdfWorld]; // #3: error -- same as _rdfModel2AsString with eventId same as IDENTIFIER_2
STAssertEqualObjects(IDENTIFIER_1, eventId, nil); // #4: fails
}
{
RdfModelWrapper *rdfModelWrapper = [identifiersToRdfModelWrappers objectForKey:IDENTIFIER_2];
rdfModel = rdfModelWrapper.rdfModel;
librdf_node *eventResource = librdf_model_get_source(rdfModel, _rdfTypeProperty, _obfuscated8CalendarEventIndividual);
librdf_node *eventIdLiteral = librdf_model_get_target(rdfModel, eventResource, _obfuscated8EventIdProperty);
NSString *eventId = [NSString stringWithCString:librdf_node_get_literal_value_as_latin1(eventIdLiteral) encoding:NSISOLatin1StringEncoding];
[self writeModel:rdfModel withRdfWorld:_rdfWorld]; // #5: ok -- same as _rdfModel2AsString with eventId same as IDENTIFIER_2
STAssertEqualObjects(IDENTIFIER_2, eventId, nil); // #6: ok
}
}
- (void)writeModel:(librdf_model *)rdfModel withRdfWorld:(librdf_world *)rdfWorld
{
raptor_world *raptorWorld = librdf_world_get_raptor(rdfWorld);
raptor_iostream *stream = raptor_new_iostream_to_file_handle(raptorWorld, stdout);
NSAssert(stream != nil, @"cannot create stream");
int flag = librdf_model_write(rdfModel, stream);
NSAssert(flag == 0, @"librdf_model_write() failed: %d", flag);
raptor_free_iostream(stream);
}
#pragma mark -
#pragma mark override SenTestCase
- (void)setUp
{
_rdfWorld = librdf_new_world();
librdf_world_open(_rdfWorld);
_rdfStorage = librdf_new_storage(_rdfWorld, "memory", NULL, NULL);
_rdfTypeProperty = LIBRDF_MS_type(_rdfWorld);
_obfuscated8NamespaceUri = librdf_new_uri(_rdfWorld, (const unsigned char *)OBFUSCATED6_NAMESPACE.UTF8String);
_obfuscated8EventIdProperty = librdf_new_node_from_uri_local_name(_rdfWorld, _obfuscated8NamespaceUri, (const unsigned char *)OBFUSCATED6_EVENT_ID_LOCAL_NAME.UTF8String);
_obfuscated8CalendarEventIndividual = librdf_new_node_from_uri_local_name(_rdfWorld, _obfuscated8NamespaceUri, (const unsigned char *)OBFUSCATED6_CALENDAR_EVENT_LOCAL_NAME.UTF8String);
_rdfParser = librdf_new_parser(_rdfWorld, NULL, "application/rdf+xml", NULL);
NSAssert(_rdfParser != nil, @"no RDF parser");
_baseUri = librdf_new_uri(_rdfWorld, (const unsigned char *)"http://www.w3.org/1999/02/22-rdf-syntax-ns#");
_rdfModel1AsString = @"<rdf:RDF \
xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" \
xmlns:j.0=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED7#\" \
xmlns:owl=\"http://www.w3.org/2002/07/owl#\" \
xmlns=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED2#\" \
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema#\" \
xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\" \
xmlns:mo=\"http://purl.org/ontology/mo/\">\
<rdf:Description rdf:about=\"http://www.OBFUSCATED5.com/event/show/2224183\">\
<rdf:type rdf:resource=\"http://www.w3.org/2000/01/rdf-schema#Resource\"/>\
<rdf:type rdf:resource=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED7#CalendarEvent\"/>\
<j.0:eventId>dc4bc97ugu7kl5hoh2spmanob4</j.0:eventId>\
<j.0:hasOrganization rdf:resource=\"http://www.OBFUSCATED1.com/2013/05/MDW#MDW\"/>\
</rdf:Description>\
</rdf:RDF>";
_rdfModel2AsString = @"<rdf:RDF \
xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" \
xmlns:j.0=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED7#\" \
xmlns:owl=\"http://www.w3.org/2002/07/owl#\" \
xmlns=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED2#\" \
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema#\" \
xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\" \
xmlns:mo=\"http://purl.org/ontology/mo/\">\
<rdf:Description rdf:about=\"http://www.OBFUSCATED4.com/veranstaltungen/uebersicht/veranstaltung-details/event/201305221830/OBFUSCATED9/\">\
<rdf:type rdf:resource=\"http://www.w3.org/2000/01/rdf-schema#Resource\"/>\
<rdf:type rdf:resource=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED7#CalendarEvent\"/>\
<j.0:eventId>cbd3mghbgas8juuh4l88rt04ec</j.0:eventId>\
<j.0:hasOrganization rdf:resource=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED3#OBFUSCATED3\"/>\
<j.0:hasLocation rdf:resource=\"http://www.OBFUSCATED1.com/2013/05/OBFUSCATED3#Konzertsaal\"/>\
</rdf:Description>\
</rdf:RDF>";
[super setUp];
}
- (void)tearDown
{
librdf_free_node(_obfuscated8EventIdProperty);
librdf_free_node(_obfuscated8CalendarEventIndividual);
librdf_free_uri(_obfuscated8NamespaceUri);
librdf_free_node(_rdfTypeProperty);
librdf_free_uri(_baseUri);
librdf_free_parser(_rdfParser);
librdf_free_storage(_rdfStorage);
librdf_free_world(_rdfWorld);
[super tearDown];
}
@end
//
// RdfModelWrapper.h
//
#import "librdf.h"
@interface RdfModelWrapper : NSObject
@property (assign, readonly) librdf_model *rdfModel;
- (id)initWithRdfModel:(librdf_model *)rdfModel;
@end
//
// RdfModelWrapper.m
//
#import "RdfModelWrapper.h"
@implementation RdfModelWrapper
- (id)initWithRdfModel:(librdf_model *)rdfModel
{
self = [super init];
if (self) {
_rdfModel = rdfModel; // RDFModelWrapper effectively takes ownership of rdfModel, i.e. is in charge of freeing it
}
return self;
}
- (void)dealloc
{
librdf_free_model(_rdfModel);
}
@end