Skip to content

Commit

Permalink
Showing 8 changed files with 228 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@
* ENTITY_OR_LITERAL = ENTITY | literal
* ENTITY = startEntity, ENTITY_OR_LITERAL*, endEntity)
*
* The {@link WellFormednessChecker} can be used to check if a stream conforms
* The {@link WellformednessChecker} can be used to check if a stream conforms
* to these rules.
*
* @see DefaultStreamReceiver
Original file line number Diff line number Diff line change
@@ -24,32 +24,32 @@

/**
* Creates a literal for each entry in a map.
*
*
* @author Christoph Böhme
*/
public final class MapToStream extends
DefaultObjectPipe<Map<?, ?>, StreamReceiver> {


private Object idKey = StreamConstants.ID;

public Object getIdKey() {
return idKey;
}

public void setIdKey(final Object idKey) {
this.idKey = idKey;
}

@Override
public void process(final Map<?, ?> map) {
final Object id = map.get(idKey);
if (id == null) {
getReceiver().startRecord(null);
getReceiver().startRecord("");
} else {
getReceiver().startRecord(id.toString());
}
for (Map.Entry<?, ?> entry: map.entrySet()) {
for (final Map.Entry<?, ?> entry: map.entrySet()) {
getReceiver().literal(entry.getKey().toString(), entry.getValue().toString());
}
getReceiver().endRecord();
Original file line number Diff line number Diff line change
@@ -26,9 +26,9 @@

/**
* Reads CG-XML files.
*
*
* @author Christoph Böhme
*
*
*/
@Description("Reads CG-XML files")
@In(XmlReceiver.class)
@@ -46,7 +46,12 @@ public final class CGXmlHandler extends DefaultXmlPipe<StreamReceiver> {
public void startElement(final String uri, final String localName,
final String qName, final Attributes attributes) {
if (RECORD_TAG.equals(localName)) {
getReceiver().startRecord(attributes.getValue("", ID_ATTR));
final String recordId = attributes.getValue("", ID_ATTR);
if (recordId == null) {
getReceiver().startRecord("");
} else {
getReceiver().startRecord(recordId);
}
} else if (ENTITY_TAG.equals(localName)) {
getReceiver().startEntity(attributes.getValue("", NAME_ATTR));
} else if (LITERAL_TAG.equals(localName)) {
Original file line number Diff line number Diff line change
@@ -156,7 +156,7 @@ private void appendChildren(final StringBuilder builder) {
private boolean strictKeyOrder;
private boolean strictValueOrder;

private final WellFormednessChecker wellFormednessChecker = new WellFormednessChecker();
private final WellformednessChecker wellformednessChecker = new WellformednessChecker();

public StreamValidator(final List<Event> expectedStream) {
this.eventStream = new EventNode(null, null);
@@ -207,7 +207,7 @@ public void startRecord(final String identifier) {
throw new ValidationException(VALIDATION_FAILED);
}

wellFormednessChecker.startRecord(identifier);
wellformednessChecker.startRecord(identifier);

validating = true;

@@ -224,7 +224,7 @@ public void endRecord() {
throw new ValidationException(VALIDATION_FAILED);
}

wellFormednessChecker.endRecord();
wellformednessChecker.endRecord();

if (!closeGroups()) {
validationFailed = true;
@@ -240,7 +240,7 @@ public void startEntity(final String name) {
throw new ValidationException(VALIDATION_FAILED);
}

wellFormednessChecker.startEntity(name);
wellformednessChecker.startEntity(name);

if (!openGroups(Event.Type.START_ENTITY, name, strictKeyOrder, strictValueOrder)) {
validationFailed = true;
@@ -255,7 +255,7 @@ public void endEntity() {
throw new ValidationException(VALIDATION_FAILED);
}

wellFormednessChecker.endEntity();
wellformednessChecker.endEntity();

if (!closeGroups()) {
validationFailed = true;
@@ -270,7 +270,7 @@ public void literal(final String name, final String value) {
throw new ValidationException(VALIDATION_FAILED);
}

wellFormednessChecker.literal(name, value);
wellformednessChecker.literal(name, value);

final List<EventNode> stackFrame = stack.peek();

@@ -292,7 +292,7 @@ public void literal(final String name, final String value) {

@Override
public void resetStream() {
wellFormednessChecker.resetStream();
wellformednessChecker.resetStream();

validating = false;
validationFailed = false;
@@ -308,7 +308,7 @@ public void closeStream() {
throw new ValidationException(VALIDATION_FAILED);
}

wellFormednessChecker.closeStream();
wellformednessChecker.closeStream();

validating = false;

Original file line number Diff line number Diff line change
@@ -19,29 +19,33 @@
import org.culturegraph.mf.framework.StreamReceiver;

/**
* A stream receiver that throws an {@link WellformednessException} if
* the stream event methods are called in an invalid order. Additionally,
* A stream receiver that throws an {@link WellformednessException} if
* the stream event methods are called in an invalid order. Additionally,
* the stream receiver checks that entity and literal names are not null.
*
*
* @see StreamValidator
* @see WellformednessException
*
*
* @author Christoph Böhme
*
*
*/
public final class WellFormednessChecker implements StreamReceiver {

public final class WellformednessChecker implements StreamReceiver {

private static final String ID_MUST_NOT_BE_NULL = "id must not be null";
private static final String NAME_MUST_NOT_BE_NULL = "name must not be null";

private static final String NOT_IN_RECORD = "Not in record";
private static final String NOT_IN_ENTITY = "Not in entity";
private static final String IN_ENTITY = "In entity";
private static final String IN_RECORD = "In record";

private int nestingLevel;

@Override
public void startRecord(final String identifier) {
if (identifier == null) {
throw new WellformednessException(ID_MUST_NOT_BE_NULL);
}
if (nestingLevel > 0) {
throw new WellformednessException(IN_RECORD);
}
@@ -50,10 +54,10 @@ public void startRecord(final String identifier) {

@Override
public void endRecord() {
if (nestingLevel < 1) {
if (nestingLevel < 1) {
throw new WellformednessException(NOT_IN_RECORD);
} else if (nestingLevel > 1) {
throw new WellformednessException(IN_ENTITY);
throw new WellformednessException(IN_ENTITY);
}
nestingLevel -= 1;
}
@@ -86,7 +90,7 @@ public void literal(final String name, final String value) {
throw new WellformednessException(NOT_IN_RECORD);
}
}

@Override
public void resetStream() {
nestingLevel = 0;
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@
import java.util.Map;

import org.culturegraph.mf.exceptions.FormatException;
import org.culturegraph.mf.stream.converter.MapToStream;
import org.culturegraph.mf.stream.sink.EventList;
import org.culturegraph.mf.stream.sink.StreamValidator;
import org.culturegraph.mf.util.StreamConstants;
@@ -29,9 +28,9 @@

/**
* Test {@link MapToStream}
*
*
* @author Christoph Böhme
*
*
*/
public final class MapToStreamTest {

@@ -51,16 +50,16 @@ public void testStringStringMap() {
expected.literal(KEYS[1], VALUES[1]);
expected.literal(StreamConstants.ID, RECORD_ID);
expected.endRecord();

final Map<String, String> map = new HashMap<String, String>();
map.put(KEYS[0], VALUES[0]);
map.put(KEYS[1], VALUES[1]);
map.put(StreamConstants.ID, RECORD_ID);

final MapToStream mapToStream = new MapToStream();

Assert.assertEquals(StreamConstants.ID, mapToStream.getIdKey());

checkResults(expected, mapToStream, map);
}

@@ -73,48 +72,48 @@ public void testIntIntMap() {
expected.literal(KEYS[1], VALUES[1]);
expected.literal(Integer.toString(INT_ID_KEY), RECORD_ID);
expected.endRecord();

final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(INT_KEYS[0], INT_VALUES[0]);
map.put(INT_KEYS[1], INT_VALUES[1]);
map.put(INT_ID_KEY, INT_RECORD_ID);

final MapToStream mapToStream = new MapToStream();
mapToStream.setIdKey(-1);

Assert.assertEquals(-1, mapToStream.getIdKey());

checkResults(expected, mapToStream, map);
}

@Test
public void testStringIntMap() {
final EventList expected = new EventList();
expected.startRecord(null);
expected.startRecord("");
expected.literal(KEYS[0], VALUES[0]);
expected.literal(KEYS[1], VALUES[1]);
expected.endRecord();

final Map<String, Integer> map = new HashMap<String, Integer>();
map.put(KEYS[0], INT_VALUES[0]);
map.put(KEYS[1], INT_VALUES[1]);

final MapToStream mapToStream = new MapToStream();

checkResults(expected, mapToStream, map);
}

private void checkResults(final EventList expected, final MapToStream mapToStream, final Map<?, ?> map) {

final StreamValidator validator = new StreamValidator(expected.getEvents());

mapToStream.setReceiver(validator);

try {
mapToStream.process(map);
mapToStream.closeStream();
} catch (FormatException e){
} catch (final FormatException e){
Assert.fail(e.toString());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -16,8 +16,6 @@
package org.culturegraph.mf.stream.converter.xml;

import org.culturegraph.mf.stream.DataFilePath;
import org.culturegraph.mf.stream.converter.xml.CGXmlHandler;
import org.culturegraph.mf.stream.converter.xml.XmlDecoder;
import org.culturegraph.mf.stream.sink.EventList;
import org.culturegraph.mf.stream.sink.StreamValidator;
import org.culturegraph.mf.stream.source.ResourceOpener;
@@ -35,27 +33,27 @@ public final class CGXmlReaderTest {
private static final String NUMBER = "Number";
private static final String POSTCODE = "Postcode";
private static final String CITY = "City";

@Test
public void testReadStringStreamReceiver() {
final ResourceOpener opener = new ResourceOpener();
final XmlDecoder saxReader = new XmlDecoder();
final CGXmlHandler cgHandler = new CGXmlHandler();
final EventList writer = new EventList();


opener.setReceiver(saxReader)
.setReceiver(cgHandler)
.setReceiver(writer);

opener.process(DataFilePath.CG_XML);
opener.closeStream();

final StreamValidator validator = new StreamValidator(writer.getEvents());
validator.setStrictRecordOrder(true);
validator.setStrictKeyOrder(true);
validator.setStrictValueOrder(true);

validator.startRecord("1");
validator.literal(NAME, "Thomas Mann");
validator.startEntity(ADDRESS);
@@ -67,7 +65,7 @@ public void testReadStringStreamReceiver() {
validator.literal(POSTCODE, null);
validator.endEntity();
validator.endRecord();
validator.startRecord(null);
validator.startRecord("");
validator.literal(NAME, "Günter Grass");
validator.startEntity(ADDRESS);
validator.startEntity(STREET);
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright 2013 Deutsche Nationalbibliothek
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.culturegraph.mf.stream.sink;

import org.culturegraph.mf.exceptions.WellformednessException;
import org.junit.Before;
import org.junit.Test;

/**
* Tests for {@link WellformednessChecker}.
*
* @author Christoph Böhme
*
*/
public final class WellformednessCheckerTest {

private static final String RECORD_ID1 = "id1";
private static final String RECORD_ID2 = "id2";
private static final String ENTITY1 = "entity1";
private static final String ENTITY2 = "entity2";
private static final String ENTITY3 = "entity3";
private static final String LITERAL1 = "literal1";
private static final String LITERAL2 = "literal2";
private static final String LITERAL3 = "literal3";
private static final String LITERAL4 = "literal4";
private static final String VALUE1 = "value1";
private static final String VALUE2 = "value2";
private static final String VALUE3 = "value3";
private static final String VALUE4 = "value4";

private WellformednessChecker wellformednessChecker;

@Before
public void setup() {
wellformednessChecker = new WellformednessChecker();
}

@Test
public void testShouldAcceptValidStream() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.literal(LITERAL1, VALUE1);
wellformednessChecker.startEntity(ENTITY1);
wellformednessChecker.literal(LITERAL2, VALUE2);
wellformednessChecker.startEntity(ENTITY2);
wellformednessChecker.literal(LITERAL3, VALUE3);
wellformednessChecker.endEntity();
wellformednessChecker.endEntity();
wellformednessChecker.endRecord();
wellformednessChecker.startRecord(RECORD_ID2);
wellformednessChecker.startEntity(ENTITY3);
wellformednessChecker.literal(LITERAL4, VALUE4);
wellformednessChecker.endEntity();
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test
public void testShouldAcceptEmptyStream() {
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnNullRecordId() {
wellformednessChecker.startRecord(null);
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnNullEntityName() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.startEntity(null);
wellformednessChecker.endEntity();
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnNullLiteralName() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.literal(null, VALUE1);
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnStartRecordInsideRecord() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.startRecord(RECORD_ID2);
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnEndRecordOutsideRecord() {
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnStartEntityOutsideRecord() {
wellformednessChecker.startEntity(ENTITY1);
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnEndEntityOutsideRecord() {
wellformednessChecker.endEntity();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnUnmatchedEndEntity() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.endEntity();
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnLiteralOutsideRecord() {
wellformednessChecker.literal(LITERAL1, VALUE1);
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnUnclosedRecord() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnUnclosedEntityAtEndRecord() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.startEntity(ENTITY1);
wellformednessChecker.endRecord();
wellformednessChecker.closeStream();
}

@Test(expected=WellformednessException.class)
public void testShouldFailOnUnclosedEntityAtCloseStream() {
wellformednessChecker.startRecord(RECORD_ID1);
wellformednessChecker.startEntity(ENTITY1);
wellformednessChecker.closeStream();
}

}

0 comments on commit b2795c7

Please sign in to comment.