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

org.jeyzer.profile.pattern.PatternUpdater Maven / Gradle / Ivy

package org.jeyzer.profile.pattern;

/*-
 * ---------------------------LICENSE_START---------------------------
 * Jeyzer Profile Updater
 * --
 * Copyright (C) 2020 - 2023 Jeyzer
 * --
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 * ----------------------------LICENSE_END----------------------------
 */


import java.util.Collection;

import org.jeyzer.profile.data.ProfileEntry;
import org.jeyzer.profile.data.validation.ProfileEntryValidator;
import org.jeyzer.profile.error.InvalidProfileEntryException;
import org.jeyzer.profile.error.InvalidPatternsException;
import org.jeyzer.profile.util.ConfigUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;

public abstract class PatternUpdater {
	
	public static final String JZR_PROFILE = "profile";
	public static final String JZR_PATTERNS = "patterns";
	

	public static final String JZR_FUNCTION = "function";
	public static final String JZR_OPERATION = "operation";
	public static final String JZR_LOCKER = "locker";
	public static final String JZR_EXCLUDE = "exclude";
	public static final String JZR_EXCLUDE_THREAD_NAME = "exclude_thread_name";
	public static final String JZR_EXECUTOR = "executor";
	public static final String JZR_EXECUTOR_THREAD_NAME = "executor_thread_name";
	
	protected Document doc;

	// functions, operations..
	protected Element typePatternsNode;
	
	// ex : all function objects
	protected NodeList targetNodes;
	
	public PatternUpdater(Document doc) throws InvalidPatternsException {
		this.doc = doc;
		
		// profile
		NodeList nodes = doc.getElementsByTagName(JZR_PROFILE);
		if (nodes.getLength() == 0)
			throw new InvalidPatternsException(JZR_PROFILE + " node is missing in target profile file " + doc.getDocumentURI());
		
		Element profileNode = (Element)nodes.item(0);
		
		// patterns
		Element patternsNode = ConfigUtil.getFirstChildNode(profileNode, JZR_PATTERNS);
		if (patternsNode == null)
			throw new InvalidPatternsException(JZR_PATTERNS + " node is missing in target profile file " + doc.getDocumentURI());
		
		typePatternsNode = getTypePatternsNode(patternsNode, true);
		
		targetNodes = typePatternsNode.getElementsByTagName(this.getName()); // can be empty 
	}

	public abstract String getName();
	
	public void updatePatterns(Element newPatterns) {
		Element newTypePatternsNode = getTypePatternsNode(newPatterns, false);
		if (newTypePatternsNode == null)
			return;
		
		NodeList newNodes = newTypePatternsNode.getElementsByTagName(this.getName());
		if (newNodes.getLength() == 0)
			return;
		
		// Build cache only if new nodes must be inserted
		Multimap targetNodeCache = buildCache(targetNodes);
		
		for (int i=0; i targetNodeCache) {
		Collection entries = targetNodeCache.get(newNode.getAttribute(ProfileEntry.JZR_NAME));
		if (entries.isEmpty())
			appendNewPattern(newNode);
		else
			insertNewPattern(newNode, entries);
	}

	private void insertNewPattern(Element newNode, Collection entries) {
		ProfileEntry lastEntry = null;
		
		for (ProfileEntry entry : entries){
			if (entry.nodeEquals(newNode))
				return; 	// already there
			else if (entry.patternEquals(newNode)){
				updatePatternOptionalFields(entry, newNode); // possibly update priority or any other field
				return;
			}
			lastEntry = entry;
		}
		
		if (lastEntry == null)
			return; // should not happen
		
		// new entry under the same name: add it after the last entry
		insertNewPattern(newNode, lastEntry);
	}

	private void insertNewPattern(Element newNode, ProfileEntry lastEntry) {
		Element nextNode = lastEntry.getNextNode();
		
		if (nextNode == null)
			appendNewPattern(newNode);
		else{
			insertNewPattern(newNode, nextNode);
		}
	}

	protected void insertNewPattern(Element newNode, Element nextNode) {
		Element newChild = (Element)newNode.cloneNode(true);
		this.doc.adoptNode(newChild);
		this.typePatternsNode.insertBefore(newChild, nextNode);
	}

	private Multimap buildCache(NodeList targetNodes) {
		Multimap targetNodeCache = LinkedHashMultimap.create();
		
		for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy