/** | |
******************************************************************************** | |
* Copyright (c) 2015-2019 Robert Bosch GmbH and others. | |
* | |
* This program and the accompanying materials are made | |
* available under the terms of the Eclipse Public License 2.0 | |
* which is available at https://www.eclipse.org/legal/epl-2.0/ | |
* | |
* SPDX-License-Identifier: EPL-2.0 | |
* | |
* Contributors: | |
* Robert Bosch GmbH - initial API and implementation | |
******************************************************************************** | |
*/ | |
package org.eclipse.app4mc.amalthea.converters.common.xpath.utils; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import org.jdom2.Document; | |
import org.jdom2.Element; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public class BulkXpathOperation { | |
private static final Logger LOGGER = LoggerFactory.getLogger(BulkXpathOperation.class); | |
/** | |
* This method takes Xml Document object and the list of Xpath Strings as input-> and returns a Map with key as | |
* Xpath and Value as the List<Element> JDOM elements | |
* | |
* @param document | |
* @param xpaths | |
* @return Map - containing Key as Xpath and Value as the List of JDOM Element's | |
*/ | |
public Map<String, List<Element>> invokeXpath(final Document document, final Collection<String> xpaths) { | |
final Map<String, List<Element>> resultsMap = new HashMap<>(); | |
try { | |
// building optimized map | |
final Map<String, XpathFragment> fragmentsMap = new HashMap<>(); | |
for (final String xpath : xpaths) { | |
/*-example Xpath : //osModel/scheduler[3] */ | |
/*- this buffer is used to populate characters of xpath fragment string till the first occurance of "/" */ | |
final StringBuilder fragmentStringBuffer = new StringBuilder(); | |
final char[] charArray = xpath.toCharArray(); | |
final int length = charArray.length; | |
XpathFragment parentFragmentObject = null; | |
for (int i = 0; i < length; i++) { | |
final char _char = charArray[i]; | |
/*- on occurance of "/" char, then the next character is also checked if it is "/" */ | |
if (_char == '/') { | |
if ((i + 1) < length) { | |
final char _char_next = charArray[i + 1]; | |
if (_char_next == '/') { | |
fragmentStringBuffer.append(_char); | |
fragmentStringBuffer.append(_char_next); | |
i++; | |
} | |
/*- on occurance of "/" char, then the next character is also checked if it is "/" | |
* Below is the case where next char is not "/" | |
* */ | |
else { | |
/*- containing only parts of the fragment */ | |
final String fragmentString = fragmentStringBuffer.toString(); | |
/*- example : | |
* | |
* - First iteration : //osModel | |
* - Second iteration : | |
* */ | |
if (fragmentString.length() > 0) { | |
/*- this the content of Xpath string from the begining till the current character (i.e. index of i)*/ | |
final String xpathSubContent_from_begining_till_current_index = xpath.substring(0, | |
i); | |
if (fragmentsMap.containsKey(xpathSubContent_from_begining_till_current_index)) { | |
parentFragmentObject = fragmentsMap | |
.get(xpathSubContent_from_begining_till_current_index); | |
} | |
else { | |
final XpathFragment fragmentObject = new XpathFragment(); | |
fragmentObject.setValue(fragmentString); | |
fragmentObject.setParent(parentFragmentObject); | |
/*-updating map*/ | |
fragmentsMap.put(xpathSubContent_from_begining_till_current_index, | |
fragmentObject); | |
/*- marking the current fragment as parent fragment for the next iteration */ | |
parentFragmentObject = fragmentObject; | |
} | |
} | |
fragmentStringBuffer.setLength(0); | |
fragmentStringBuffer.append("./"); | |
} | |
} | |
} | |
else { | |
fragmentStringBuffer.append(_char); | |
} | |
} | |
/*- setting last fragment value, as it will not set in the previous loop */ | |
final String fragmentString = fragmentStringBuffer.toString(); | |
if (fragmentString.length() > 0) { | |
final XpathFragment fragment = new XpathFragment(); | |
fragment.setValue(fragmentString); | |
fragment.setParent(parentFragmentObject); | |
/*-updating map*/ | |
fragmentsMap.put(xpath, fragment); | |
} | |
} | |
/*- Printing the contents of FragmentsMap */ | |
final Set<String> keySet = fragmentsMap.keySet(); | |
for (final String string : keySet) { | |
LOGGER.trace("Xpath Fragment : {} associated Xpath chunk : {}", string, fragmentsMap.get(string).getValue()); | |
} | |
/*- execute Xpath evaluation */ | |
final Element rootElement = document.getRootElement(); | |
for (final String xpath : xpaths) { | |
if (!resultsMap.containsKey(xpath)) { | |
final XpathFragment xpathFragment = fragmentsMap.get(xpath); | |
if (xpathFragment != null) { | |
xpathFragment.visit(rootElement); | |
final List<Element> xmlElements = xpathFragment.getXmlElements(); | |
resultsMap.put(xpath, xmlElements); | |
LOGGER.trace("xpath : {} elements : {}", xpath, xmlElements.size()); | |
} | |
} | |
} | |
} | |
catch (final Exception e) { | |
LOGGER.error(e.getMessage(), e); | |
throw e; | |
} | |
return resultsMap; | |
} | |
} |