| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.modules.ant.freeform; |
| |
| import java.io.IOException; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Set; |
| import javax.swing.event.ChangeListener; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.api.project.ProjectManager; |
| import org.netbeans.spi.project.SubprojectProvider; |
| import org.openide.ErrorManager; |
| import org.openide.filesystems.FileObject; |
| import org.openide.xml.XMLUtil; |
| import org.w3c.dom.Element; |
| |
| /** |
| * Manages list of subprojects. |
| * @author Jesse Glick |
| * @see "#46713" |
| */ |
| final class Subprojects implements SubprojectProvider { |
| |
| private final FreeformProject project; |
| |
| public Subprojects(FreeformProject project) { |
| this.project = project; |
| } |
| |
| @Override |
| public Set<? extends Project> getSubprojects() { |
| return new LazySubprojectsSet(); |
| } |
| |
| /**Analyzes subprojects element. |
| * Works in two modes: |
| * 1. Lazy mode, detects only if the set of subprojects would be empty. |
| * Enabled if the provided subprojects parameter is null. |
| * The subprojects set is empty if createSubprojects(null) == null. |
| * Used by the LazySubprojectsSet, see #58639. Works as fast as possible. |
| * 2. Full mode, creates the set of projects. |
| * Enabled if the subprojects parameter is not-null. |
| * The provided instance of Set is filled by the projects and returned. |
| * |
| * This method never allocates a new set. |
| */ |
| private Set<Project> createSubprojects(Set<Project> subprojects) { |
| Element config = project.getPrimaryConfigurationData(); |
| Element subprjsEl = XMLUtil.findElement(config, "subprojects", FreeformProjectType.NS_GENERAL); // NOI18N |
| if (subprjsEl != null) { |
| for (Element prjEl : XMLUtil.findSubElements(subprjsEl)) { |
| assert prjEl.getLocalName().equals("project") : "Bad element " + prjEl + " in <subprojects> for " + project; |
| String rawtext = XMLUtil.findText(prjEl); |
| assert rawtext != null : "Need text content for <project> in " + project; |
| String evaltext = project.evaluator().evaluate(rawtext); |
| if (evaltext == null) { |
| continue; |
| } |
| FileObject subprjDir = project.helper().resolveFileObject(evaltext); |
| if (subprjDir == null) { |
| continue; |
| } |
| try { |
| Project p = ProjectManager.getDefault().findProject(subprjDir); |
| if (p != null) { |
| if (subprojects == null) { |
| return Collections.emptySet(); |
| } |
| else { |
| subprojects.add(p); |
| } |
| } |
| } catch (IOException e) { |
| org.netbeans.modules.ant.freeform.Util.err.notify(ErrorManager.INFORMATIONAL, e); |
| } |
| } |
| } |
| |
| return subprojects; |
| } |
| |
| @Override |
| public void addChangeListener(ChangeListener listener) { |
| // XXX |
| } |
| |
| @Override |
| public void removeChangeListener(ChangeListener listener) { |
| // XXX |
| } |
| |
| /**Fix for #58639: the subprojects should be loaded lazily, so invoking the popup menu |
| * with "Open Required Projects" is fast. |
| */ |
| private final class LazySubprojectsSet implements Set<Project> { |
| |
| private Set<Project> delegateTo = null; |
| |
| private synchronized Set<Project> getDelegateTo() { |
| if (delegateTo == null) { |
| delegateTo = createSubprojects(new HashSet<Project>()); |
| } |
| |
| return delegateTo; |
| } |
| |
| @Override |
| public boolean contains(Object o) { |
| return getDelegateTo().contains(o); |
| } |
| |
| @Override |
| public boolean add(Project p) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean remove(Object o) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean removeAll(Collection c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean retainAll(Collection c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean addAll(Collection<? extends Project> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean containsAll(Collection c) { |
| return getDelegateTo().containsAll(c); |
| } |
| |
| @Override |
| public <T> T[] toArray(T[] a) { |
| return getDelegateTo().toArray(a); |
| } |
| |
| @Override |
| public void clear() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int size() { |
| return getDelegateTo().size(); |
| } |
| |
| @Override |
| public synchronized boolean isEmpty() { |
| if (delegateTo == null) { |
| return createSubprojects(null) == null; |
| } else { |
| return delegateTo.isEmpty(); |
| } |
| } |
| |
| @Override |
| public Iterator<Project> iterator() { |
| return getDelegateTo().iterator(); |
| } |
| |
| @Override |
| public Object[] toArray() { |
| return getDelegateTo().toArray(); |
| } |
| |
| @Override |
| public int hashCode() { |
| return getDelegateTo().hashCode(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| return getDelegateTo().equals(obj); |
| } |
| |
| @Override |
| public String toString() { |
| return getDelegateTo().toString(); |
| } |
| |
| } |
| |
| } |