package org.eclipse.jst.jsf.facelet.core.internal.registry.taglib; import java.util.Collections; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.jst.jsf.common.internal.locator.ILocatorProvider; import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResource; import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceContainer; import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceFragment; import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceFragment.Type; import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceLocator; import org.eclipse.jst.jsf.designtime.internal.resources.JSFResourceChangeListener; import org.eclipse.jst.jsf.designtime.internal.resources.JSFResourceContainer; import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.JSFResourceBasedTagRecord.Builder; import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.Listener.TaglibChangedEvent; import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.Listener.TaglibChangedEvent.CHANGE_TYPE; /** * A taglib locator that locates composite components, which a located as a type * of JSF locatable resource. * * @author cbateman * */ public class CompositeComponentTaglibLocator extends AbstractFaceletTaglibLocator { private final class ResourceLocatorChangeListener extends JSFResourceChangeListener { @Override public void changed(final JSFResourceChangedEvent event) { final Builder builder = new Builder(); switch (event.getChangeType()) { case ADDED: case CHANGED: { handleAddAndChange(event, builder); } break; case REMOVED: { handleRemove(event, builder); } break; } } private void handleRemove(final JSFResourceChangedEvent event, final Builder builder) { //Bug 324234 - NPE from CompositeComponentTaglibLocator if (event != null) { IJSFResourceFragment oldValue = event.getOldValue(); if (oldValue != null) { Type type = oldValue.getType(); if (type != null) { List<TaglibChangedEvent> events = Collections.EMPTY_LIST; switch (type) { case RESOURCE: { events = handleRemoveResource(event, builder); } break; case CONTAINER: { events = handleRemoveContainer(event, builder); } break; } _records = builder.merge(events, _records); for (final TaglibChangedEvent fireEvent : events) { fireChangeEvent(fireEvent); } } } } } private List<TaglibChangedEvent> handleRemoveContainer( final JSFResourceChangedEvent event, final Builder builder) { final IJSFResourceFragment oldValue = event.getOldValue(); builder.addLibrary((IJSFResourceContainer) oldValue, CHANGE_TYPE.REMOVED); return builder.createRemove(CompositeComponentTaglibLocator.this, _records); } private List<TaglibChangedEvent> handleRemoveResource( final JSFResourceChangedEvent event, final Builder builder) { final IJSFResourceFragment oldValue = event.getOldValue(); builder.addTag((IJSFResource) oldValue, CHANGE_TYPE.REMOVED); return builder.createRemove(CompositeComponentTaglibLocator.this, _records); } private void handleAddAndChange(final JSFResourceChangedEvent event, final Builder builder) { List<TaglibChangedEvent> events = Collections.EMPTY_LIST; switch (event.getNewValue().getType()) { case CONTAINER: // if it's a fragment handle as a possible library add events = handleFolderAddChange(event, builder); break; case RESOURCE: // otherwise, handle as a file add. events = handleFileAddChange(event, builder); break; } _records = builder.merge(events, _records); for (final TaglibChangedEvent fireEvent : events) { fireChangeEvent(fireEvent); } } private List<TaglibChangedEvent> handleFolderAddChange( final JSFResourceChangedEvent event, final Builder builder) { final JSFResourceContainer newValue = (JSFResourceContainer) event .getNewValue(); builder.addLibrary(newValue, CHANGE_TYPE.ADDED); return builder.createMerge(CompositeComponentTaglibLocator.this, _records); } private List<TaglibChangedEvent> handleFileAddChange( final JSFResourceChangedEvent event, final Builder builder) { final IJSFResource newValue = (IJSFResource) event.getNewValue(); builder.addTag(newValue, CHANGE_TYPE.ADDED); return builder.createMerge(CompositeComponentTaglibLocator.this, _records); } } /** * the id of the locator strategy. */ public static final String ID = CompositeComponentTaglibLocator.class .getCanonicalName(); private static final String DISPLAY_NAME = "Composite Composite Tag Lib Locator"; //$NON-NLS-1$ private final ILocatorProvider<IJSFResourceLocator> _locatorProvider; private Map<String, JSFResourceBasedTagRecord> _records; private final ResourceLocatorChangeListener _listener; /** * @param locatorProvider */ public CompositeComponentTaglibLocator( final ILocatorProvider<IJSFResourceLocator> locatorProvider) { super(ID, DISPLAY_NAME); _locatorProvider = locatorProvider; _locatorProvider.initialize(); _listener = new ResourceLocatorChangeListener(); } @Override public void start(final IProject initialContext) { for (final IJSFResourceLocator locator : _locatorProvider.getLocators()) { locator.start(initialContext); locator.addListener(_listener); } final Builder builder = new Builder(); for (final IJSFResourceLocator locator : _locatorProvider.getLocators()) { final List<IJSFResourceFragment> resources = locator .locate(initialContext); for (final IJSFResourceFragment resource : resources) { if (resource.getType() == Type.RESOURCE) { builder.addTag((IJSFResource) resource, CHANGE_TYPE.ADDED); } } } _records = builder.build(); super.start(initialContext); } @Override public void stop() { for (final IJSFResourceLocator locator : _locatorProvider.getLocators()) { locator.stop(); } super.stop(); } @Override protected Map<String, ? extends IFaceletTagRecord> doLocate( final IProject context) { return Collections.unmodifiableMap(_records); } }