001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.http.protocol.transaction;
007:
008: import java.util.ArrayList;
009: import java.util.Collection;
010: import java.util.List;
011: import java.util.Map;
012:
013: import org.xml.sax.SAXException;
014:
015: import info.aduna.xml.SimpleSAXAdapter;
016:
017: import org.openrdf.http.protocol.transaction.operations.AddStatementOperation;
018: import org.openrdf.http.protocol.transaction.operations.ClearNamespacesOperation;
019: import org.openrdf.http.protocol.transaction.operations.ClearOperation;
020: import org.openrdf.http.protocol.transaction.operations.RemoveNamespaceOperation;
021: import org.openrdf.http.protocol.transaction.operations.RemoveStatementsOperation;
022: import org.openrdf.http.protocol.transaction.operations.SetNamespaceOperation;
023: import org.openrdf.http.protocol.transaction.operations.TransactionOperation;
024: import org.openrdf.model.Literal;
025: import org.openrdf.model.Resource;
026: import org.openrdf.model.URI;
027: import org.openrdf.model.Value;
028: import org.openrdf.model.ValueFactory;
029: import org.openrdf.model.impl.ValueFactoryImpl;
030:
031: /**
032: * Parses an RDF transaction document into a collection of
033: * {@link TransactionOperation} objects.
034: */
035: class TransactionSAXParser extends SimpleSAXAdapter {
036:
037: private ValueFactory valueFactory;
038:
039: private List<TransactionOperation> txn;
040:
041: private List<Value> parsedValues = new ArrayList<Value>();
042:
043: public TransactionSAXParser() {
044: this (new ValueFactoryImpl());
045: }
046:
047: public TransactionSAXParser(ValueFactory valueFactory) {
048: this .valueFactory = valueFactory;
049: }
050:
051: /**
052: * get the parsed transaction
053: *
054: * @return the parsed transaction
055: */
056: public Collection<TransactionOperation> getTxn() {
057: return txn;
058: }
059:
060: @Override
061: public void startDocument() throws SAXException {
062: txn = new ArrayList<TransactionOperation>();
063: }
064:
065: @Override
066: public void startTag(String tagName, Map<String, String> atts,
067: String text) throws SAXException {
068: if (TransactionXMLConstants.URI_TAG.equals(tagName)) {
069: parsedValues.add(valueFactory.createURI(text));
070: } else if (TransactionXMLConstants.BNODE_TAG.equals(tagName)) {
071: parsedValues.add(valueFactory.createBNode(text));
072: } else if (TransactionXMLConstants.LITERAL_TAG.equals(tagName)) {
073: String lang = atts.get(TransactionXMLConstants.LANG_ATT);
074: String datatype = atts
075: .get(TransactionXMLConstants.DATATYPE_ATT);
076:
077: Literal lit;
078: if (lang != null) {
079: lit = valueFactory.createLiteral(text, lang);
080: } else if (datatype != null) {
081: URI dtURI = valueFactory.createURI(datatype);
082: lit = valueFactory.createLiteral(text, dtURI);
083: } else {
084: lit = valueFactory.createLiteral(text);
085: }
086:
087: parsedValues.add(lit);
088: } else if (TransactionXMLConstants.NULL_TAG.equals(tagName)) {
089: parsedValues.add(null);
090: } else if (TransactionXMLConstants.SET_NAMESPACE_TAG
091: .equals(tagName)) {
092: String prefix = atts
093: .get(TransactionXMLConstants.PREFIX_ATT);
094: String name = atts.get(TransactionXMLConstants.NAME_ATT);
095: txn.add(new SetNamespaceOperation(prefix, name));
096: } else if (TransactionXMLConstants.REMOVE_NAMESPACE_TAG
097: .equals(tagName)) {
098: String prefix = atts
099: .get(TransactionXMLConstants.PREFIX_ATT);
100: txn.add(new RemoveNamespaceOperation(prefix));
101: } else if (TransactionXMLConstants.CLEAR_NAMESPACES_TAG
102: .equals(tagName)) {
103: txn.add(new ClearNamespacesOperation());
104: }
105: }
106:
107: @Override
108: public void endTag(String tagName) throws SAXException {
109: if (TransactionXMLConstants.ADD_STATEMENT_TAG.equals(tagName)) {
110: txn.add(createAddStatementOperation());
111: } else if (TransactionXMLConstants.REMOVE_STATEMENTS_TAG
112: .equals(tagName)) {
113: txn.add(createRemoveStatementsOperation());
114: } else if (TransactionXMLConstants.CLEAR_TAG.equals(tagName)) {
115: txn.add(createClearOperation());
116: }
117: }
118:
119: private TransactionOperation createClearOperation()
120: throws SAXException {
121: Resource[] contexts = createContexts(0);
122: parsedValues.clear();
123:
124: return new ClearOperation(contexts);
125: }
126:
127: private TransactionOperation createAddStatementOperation()
128: throws SAXException {
129: if (parsedValues.size() < 3) {
130: throw new SAXException(
131: "At least three values required for AddStatementOperation, found: "
132: + parsedValues.size());
133: }
134:
135: try {
136: Resource subject = (Resource) parsedValues.get(0);
137: URI predicate = (URI) parsedValues.get(1);
138: Value object = parsedValues.get(2);
139: Resource[] contexts = createContexts(3);
140:
141: parsedValues.clear();
142:
143: if (subject == null || predicate == null || object == null) {
144: throw new SAXException(
145: "Subject, predicate and object cannot be null for an AddStatementOperation");
146: }
147: return new AddStatementOperation(subject, predicate,
148: object, contexts);
149: } catch (ClassCastException e) {
150: throw new SAXException(
151: "Invalid argument(s) for AddStatementOperation", e);
152: }
153: }
154:
155: private TransactionOperation createRemoveStatementsOperation()
156: throws SAXException {
157: if (parsedValues.size() < 3) {
158: throw new SAXException(
159: "At least three values required for RemoveStatementsOperation, found: "
160: + parsedValues.size());
161: }
162:
163: try {
164: Resource subject = (Resource) parsedValues.get(0);
165: URI predicate = (URI) parsedValues.get(1);
166: Value object = parsedValues.get(2);
167: Resource[] contexts = createContexts(3);
168:
169: parsedValues.clear();
170:
171: return new RemoveStatementsOperation(subject, predicate,
172: object, contexts);
173: } catch (ClassCastException e) {
174: throw new SAXException(
175: "Invalid argument(s) for RemoveStatementsOperation",
176: e);
177: }
178: }
179:
180: private Resource[] createContexts(int startIdx) throws SAXException {
181: List<Resource> contexts = new ArrayList<Resource>();
182:
183: for (int i = startIdx; i < parsedValues.size(); i++) {
184: Value contextCandidate = parsedValues.get(startIdx);
185:
186: if (contextCandidate == null
187: || contextCandidate instanceof Resource) {
188: contexts.add((Resource) contextCandidate);
189: } else {
190: throw new SAXException("Invalid context value: "
191: + contextCandidate.getClass());
192: }
193: }
194:
195: return contexts.toArray(new Resource[contexts.size()]);
196: }
197: }
|