package org.jactr.tools.grapher.core.selector; /* * default logging */ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Executor; import javolution.util.FastList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.chunk.IChunk; import org.jactr.core.chunk.ISubsymbolicChunk; import org.jactr.core.chunk.event.ChunkEvent; import org.jactr.core.chunk.event.ChunkListenerAdaptor; import org.jactr.core.chunk.event.IChunkListener; import org.jactr.core.chunk.four.ISubsymbolicChunk4; import org.jactr.core.chunk.link.IAssociativeLink; import org.jactr.core.concurrent.ExecutorServices; import org.jactr.core.event.IParameterEvent; import org.jactr.core.event.IParameterListener; import org.jactr.core.module.declarative.associative.IAssociativeLinkContainer; import org.jactr.tools.grapher.core.container.IProbeContainer; public class ChunkSelector extends AbstractNameSelector<IChunk> { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(ChunkSelector.class); private Collection<LinkSelector> _linkSelectors; private IParameterListener _pListener; private IChunkListener _cListener; private Set<IAssociativeLink> _installed; public ChunkSelector(String regex) { super(regex); _installed = new HashSet<IAssociativeLink>(); _linkSelectors = new ArrayList<LinkSelector>(); _pListener = new IParameterListener() { public void parameterChanged(IParameterEvent pe) { if (((ISubsymbolicChunk) pe.getSource()).getParentChunk().isEncoded()) if (pe.getParameterName().equalsIgnoreCase(ISubsymbolicChunk4.LINKS)) checkLinks(((ISubsymbolicChunk) pe.getSource()).getParentChunk()); } }; _cListener = new ChunkListenerAdaptor() { @Override public void chunkEncoded(ChunkEvent event) { checkLinks(event.getSource()); } }; } @Override protected String getName(IChunk element) { return element.getSymbolicChunk().getName(); } public void add(ISelector selector) { if (selector instanceof LinkSelector) _linkSelectors.add((LinkSelector) selector); } @Override public IProbeContainer install(IChunk element, IProbeContainer container) { IProbeContainer rtnContainer = super.install(element, container); Executor executor = ExecutorServices.INLINE_EXECUTOR; element.addListener(_pListener, executor); element.addListener(_cListener, executor); if (element.isEncoded()) checkLinks(element); return rtnContainer; } private void checkLinks(IChunk chunk) { FastList<IAssociativeLink> links = FastList.newInstance(); IAssociativeLinkContainer alc = chunk .getAdapter(IAssociativeLinkContainer.class); alc.getOutboundLinks(links); for (IAssociativeLink link : links) checkLink(link, getProbeContainer(chunk)); FastList.recycle(links); } /** * this will be called anytime new links are added or removed. Which could * result in duplicate installs, so we track who we've installed already * * @param link * @param container */ private void checkLink(IAssociativeLink link, IProbeContainer container) { for (LinkSelector selector : _linkSelectors) if (selector.matches(link) && !_installed.contains(link)) { selector.install(link, container); _installed.add(link); } } }