All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.metamodel.xml.XmlSaxContentHandler Maven / Gradle / Ivy

There is a newer version: 5.3.3
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.metamodel.xml;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.metamodel.data.RowPublisher;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * SAX handler for publishing records based on xpath expressions.
 */
class XmlSaxContentHandler extends DefaultHandler {

	private final boolean _checkAttributes;
	private final String _rowXpath;
	private final String[] _valueXpaths;
	private final StringBuilder _pathBuilder;
	private final StringBuilder _valueBuilder;
	private final RowPublisher _rowPublisher;
	private final Map _indexIndexes;
	private final Map _indexCounters;
	private volatile Object[] _rowValues;
	private volatile int _xpathIndex;

	public XmlSaxContentHandler(String rowXpath, RowPublisher rowPublisher,
			String... valueXpaths) {
		_indexCounters = new HashMap();
		_indexIndexes = new HashMap();
		_rowXpath = rowXpath;
		_rowPublisher = rowPublisher;
		_valueXpaths = valueXpaths;
		_rowValues = new Object[valueXpaths.length];
		boolean checkAttributes = false;
		for (int i = 0; i < valueXpaths.length; i++) {
			String xpath = valueXpaths[i];

			if (XmlSaxDataContext.COLUMN_NAME_ROW_ID.equals(xpath)) {
				// we use the indexing mechanism also for the row id.
				xpath = "index(" + xpath + ")";
			}

			if (xpath.startsWith("index(") && xpath.endsWith(")")) {
				xpath = xpath.substring("index(".length(), xpath.length() - 1);
				_indexCounters.put(xpath, new AtomicInteger(-1));
				_indexIndexes.put(xpath, i);

			} else if (xpath.indexOf('@') != -1) {
				checkAttributes = true;
			}
		}
		_checkAttributes = checkAttributes;
		_xpathIndex = -1;
		_pathBuilder = new StringBuilder();
		_valueBuilder = new StringBuilder();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		_pathBuilder.append('/');
		_pathBuilder.append(qName);

		if (_checkAttributes) {
			for (int i = 0; i < attributes.getLength(); i++) {
				String attributeName = attributes.getQName(i);
				String attributeValue = attributes.getValue(i);
				startAttribute(attributeName, attributeValue);
				endAttribute(attributeName, attributeValue);
			}
		}

		String xpath = _pathBuilder.toString();

		AtomicInteger indexCounter = _indexCounters.get(xpath);
		if (indexCounter != null) {
			indexCounter.incrementAndGet();
		}

		_xpathIndex = indexOfXpath(xpath);
	}

	private int indexOfXpath(String path) {
		if (path == null || path.length() == 0) {
			return -1;
		}
		for (int i = 0; i < _valueXpaths.length; i++) {
			if (path.equals(_valueXpaths[i])) {
				return i;
			}
		}
		return -1;
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if (_xpathIndex != -1) {
			_valueBuilder.append(ch, start, length);
		}
	}

	private void startAttribute(String attributeName, String attributeValue) {
		_pathBuilder.append('@');
		_pathBuilder.append(attributeName);

		int indexOfXpath = indexOfXpath(_pathBuilder.toString());
		if (indexOfXpath != -1) {
			_rowValues[indexOfXpath] = attributeValue;
		}
	}

	private void endAttribute(String attributeName, String attributeValue) {
		_pathBuilder.setLength(_pathBuilder.length() - attributeName.length()
				- 1);
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if (_xpathIndex != -1) {
			_rowValues[_xpathIndex] = _valueBuilder.toString().trim();
		}
		_xpathIndex = -1;
		_valueBuilder.setLength(0);

		if (_rowXpath.equals(_pathBuilder.toString())) {
			insertRowIndexes();

			boolean more = _rowPublisher.publish(_rowValues);
			if (!more) {
				throw new XmlStopParsingException();
			}
			_rowValues = new Object[_valueXpaths.length];
		}

		_pathBuilder.setLength(_pathBuilder.length() - qName.length() - 1);
	}

	private void insertRowIndexes() {
		Set> entrySet = _indexIndexes.entrySet();
		for (Entry entry : entrySet) {
			String xpath = entry.getKey();
			Integer indexIndex = entry.getValue();
			AtomicInteger indexCount = _indexCounters.get(xpath);
			_rowValues[indexIndex] = indexCount.get();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy