/*******************************************************************************
* Copyright (c) 2009 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.validation.internal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.jboss.tools.common.el.core.ELReference;
import org.jboss.tools.common.validation.ValidationELReference;
import org.jboss.tools.common.xml.XMLUtilities;
import org.w3c.dom.Element;
/**
* @author Alexey Kazakov
*/
public class ELValidatorContext extends LinkCollection {
private Map<String, Set<ELReference>> elsByVariableName = new HashMap<String, Set<ELReference>>();
private Map<ELReference, Set<String>> variableNamesByEl = new HashMap<ELReference, Set<String>>();
private Map<IPath, Set<ELReference>> elsByResource = new HashMap<IPath, Set<ELReference>>();
public ELValidatorContext(String id) {
super(id);
}
/**
* Save link between EL and variable name.
* @param variableName
* @param el
*/
public synchronized void addLinkedEl(String variableName, ELReference el) {
Set<ELReference> linkedEls = elsByVariableName.get(variableName);
if(linkedEls==null) {
// create set of linked ELs with variable name.
linkedEls = new HashSet<ELReference>();
elsByVariableName.put(variableName, linkedEls);
}
// save linked ELs.
// don't save links if there are more than 500 ELs for the var name.
if(linkedEls.size()<500) {
if(linkedEls.add(el)) {
modifications++;
}
// Save link between EL and variable names.
Set<String> variableNames = variableNamesByEl.get(el);
if(variableNames==null) {
variableNames = new HashSet<String>();
variableNamesByEl.put(el, variableNames);
}
if(variableNames.add(variableName.intern())) {
modifications++;
}
}
// Save link between EL and resource.
Set<ELReference> els = elsByResource.get(el.getPath());
if(els==null) {
els = new HashSet<ELReference>();
elsByResource.put(el.getPath(), els);
}
if(els.add(el)) {
modifications++;
}
}
public synchronized void removeLinkedEls(Set<IFile> resorces) {
for (IFile file : resorces) {
removeLinkedEls(file);
}
}
public synchronized void removeLinkedEls(IFile resource) {
String name = resource.getFullPath().toString(); // Resource path is also a variable name
Set<ELReference> linkedEls = elsByVariableName.remove(name);
if(linkedEls!=null ) {
modifications++;
for (ELReference el : linkedEls) {
Set<String> variableNames = variableNamesByEl.get(el);
if(variableNames!=null) {
if(variableNames.remove(name)) {
modifications++;
}
if(variableNames.isEmpty()) {
variableNamesByEl.remove(el);
}
}
}
}
Set<ELReference> els = elsByResource.get(resource.getFullPath());
if(els!=null) {
if(elsByResource.remove(resource.getFullPath()) != null) {
modifications++;
}
for (ELReference el : els) {
Set<String> names = variableNamesByEl.get(el);
if(names!=null) {
String[] nameStrins = names.toArray(new String[0]);
for (int i = 0; i < nameStrins.length; i++) {
removeLinkedEl(nameStrins[i], el);
}
}
}
}
}
public synchronized void removeLinkedEl(ELReference el) {
Set<String> names = variableNamesByEl.remove(el);
if(names==null) {
return;
}
if(!names.isEmpty()) {
modifications++;
}
for (String name : names) {
Set<ELReference> els = elsByVariableName.get(name);
if(els!=null) {
els.remove(el);
if(els.isEmpty()) {
elsByVariableName.remove(name);
}
}
}
}
/**
* Removes link between EL and variable name.
* @param name
* @param el
*/
public synchronized void removeLinkedEl(String name, ELReference el) {
Set<ELReference> linkedEls = elsByVariableName.get(name);
if(linkedEls!=null) {
if(linkedEls.remove(el)) {
modifications++;
}
if(linkedEls.isEmpty()) {
elsByVariableName.remove(name);
}
}
// Remove link between EL and variable names.
Set<String> variableNames = variableNamesByEl.get(el);
if(variableNames!=null) {
if(variableNames.remove(name)) {
modifications++;
}
if(variableNames.isEmpty()) {
variableNamesByEl.remove(el);
}
}
}
/**
* Return ELs with given variable name
* @param variableName
* @return
*/
public synchronized Set<ELReference> getElsByVariableName(String variableName) {
return elsByVariableName.get(variableName);
}
/**
* @param names
* @return
*/
public synchronized Set<ELReference> getElsByVariableNames(Set<String> names) {
Set<ELReference> result = new HashSet<ELReference>();
for(String name : names) {
Set<ELReference> els = getElsByVariableName(name);
if(els!=null) {
result.addAll(els);
}
}
return result;
}
/*
* (non-Javadoc)
* @see org.jboss.tools.jst.web.kb.internal.validation.LinkCollection#clearAll()
*/
@Override
public synchronized void clearAll() {
super.clearAll();
elsByVariableName.clear();
variableNamesByEl.clear();
elsByResource.clear();
}
/*
* (non-Javadoc)
* @see org.jboss.tools.jst.web.kb.internal.validation.LinkCollection#store(org.w3c.dom.Element)
*/
@Override
public synchronized void store(Element root, Map<String, String> pathIds) {
super.store(root, pathIds);
Set<String> variables = elsByVariableName.keySet();
for (String name: variables) {
Set<ELReference> els = elsByVariableName.get(name);
if(els == null) {
continue;
}
for (ELReference el: els) {
Element linkedEl = XMLUtilities.createElement(root, "linked-el"); //$NON-NLS-1$
linkedEl.setAttribute("name", ELReference.getAlias(pathIds, name)); //$NON-NLS-1$
el.store(linkedEl, pathIds);
}
}
}
/*
* (non-Javadoc)
* @see org.jboss.tools.jst.web.kb.internal.validation.LinkCollection#load(org.w3c.dom.Element)
*/
@Override
public synchronized void load(Element root, Map<String, String> pathAliases) {
super.load(root, pathAliases);
if(root == null) {
return;
}
Element[] linkedEls = XMLUtilities.getChildren(root, "linked-el"); //$NON-NLS-1$
if(linkedEls != null) {
for (int i = 0; i < linkedEls.length; i++) {
String name = linkedEls[i].getAttribute("name"); //$NON-NLS-1$
if(name == null || name.trim().length() == 0) {
continue;
}
name = ELReference.getPath(pathAliases, name);
ELReference el = new ValidationELReference();
el.load(linkedEls[i], pathAliases);
el.setNeedToInitMarkers(true);
addLinkedEl(name, el);
}
}
}
}