001: package net.refractions.udig.catalog.ui.workflow;
002:
003: import java.io.IOException;
004: import java.net.URL;
005: import java.text.MessageFormat;
006: import java.util.ArrayList;
007: import java.util.Collection;
008: import java.util.HashMap;
009: import java.util.HashSet;
010: import java.util.List;
011: import java.util.Map;
012: import java.util.Set;
013:
014: import net.refractions.udig.catalog.CatalogPlugin;
015: import net.refractions.udig.catalog.IGeoResource;
016: import net.refractions.udig.catalog.IService;
017: import net.refractions.udig.catalog.ui.internal.Messages;
018:
019: import org.eclipse.core.runtime.IProgressMonitor;
020: import org.eclipse.core.runtime.SubProgressMonitor;
021:
022: /**
023: *
024: * State selects IGeoResources. The selected resources are those in the {@link #getResources()} map. The keys are the selected
025: * resources and the values are the parents. State normally uses a ConnectionState but it isn't required is {@link #setServices(List)}
026: * is used to set the services.
027: *
028: * @author Justin Deolive
029: * @since 1.1.0
030: */
031: public class ResourceSelectionState extends Workflow.State {
032:
033: /** list of resources * */
034: Map<IGeoResource, IService> resources;
035: private Collection<IService> services;
036:
037: public Collection<IService> getServices() {
038: if (services != null)
039: return services;
040: ConnectionState state = getWorkflow().getState(
041: ConnectionState.class);
042: if (state == null)
043: return null; // could occur if the connection state added dynamically
044:
045: return state.getServices();
046: }
047:
048: public void setServices(Collection<IService> services) {
049: this .services = services;
050: }
051:
052: public void setResources(Map<IGeoResource, IService> resources) {
053: this .resources = resources;
054: }
055:
056: public Map<IGeoResource, IService> getResources() {
057: return resources;
058: }
059:
060: @Override
061: public void init(IProgressMonitor monitor) throws IOException {
062: super .init(monitor);
063:
064: // try to generate some default resources based on context
065: resources = new HashMap<IGeoResource, IService>();
066:
067: // use the context object to try and match a resource
068: Object context = getWorkflow().getContext();
069: if (context != null) {
070: URL url = CatalogPlugin.locateURL(context);
071: if (url != null) {
072: addResource(monitor, url);
073: } else if (context instanceof Iterable) {
074: Iterable iterable = (Iterable) context;
075: for (Object object : iterable) {
076: url = CatalogPlugin.locateURL(object);
077: if (url != null)
078: addResource(monitor, url);
079: }
080: }
081: }
082:
083: // look through all the services, automatically "select" those with
084: // only a single member
085: // TODO: replace this with a preference or hinting system
086: Collection<IService> services = getServices();
087: List<IService> toRemove = new ArrayList<IService>();
088: for (IService service : services) {
089: List<? extends IGeoResource> members = service
090: .members(monitor);
091: if (members != null && members.size() < 1) {
092: toRemove.add(service);
093: continue;
094: }
095: if (members != null && members.size() == 1) {
096: resources.put(members.get(0), service);
097: }
098: // else {
099: // for( IGeoResource resource : members ) {
100: // resources.put(resource, service);
101: // }
102: // }
103: }
104: if (!toRemove.isEmpty())
105: services.removeAll(toRemove);
106: }
107:
108: private void addResource(IProgressMonitor monitor, URL url)
109: throws IOException {
110: IGeoResource match = match(getServices(), url, monitor);
111: if (match != null) {
112: resources.put(match, match.service(monitor));
113: }
114: }
115:
116: @Override
117: public boolean run(IProgressMonitor monitor) throws IOException {
118: // complete if all the resources have been "selected"
119:
120: if (resources == null || resources.isEmpty())
121: return false;
122:
123: int count = 0;
124:
125: Set<IService> parents = new HashSet<IService>();
126:
127: for (Map.Entry<IGeoResource, IService> entry : resources
128: .entrySet()) {
129: parents.add(entry.getValue());
130: }
131:
132: Collection<IService> services = getServices();
133: try {
134: monitor.beginTask("", services.size() * 10); //$NON-NLS-1$
135: for (IService service : services) {
136: SubProgressMonitor subMonitor = new SubProgressMonitor(
137: monitor, 10);
138: try {
139:
140: URL identifier = service.getIdentifier();
141: monitor.setTaskName(MessageFormat.format(
142: Messages.ResourceSelectionState_taskName,
143: new Object[] { identifier.getProtocol()
144: + "://" + identifier.getPath() })); //$NON-NLS-1$
145: count += service.members(subMonitor).size();
146: } finally {
147: subMonitor.done();
148: }
149: }
150: } finally {
151: monitor.done();
152: }
153:
154: return count == resources.size()
155: || parents.size() == getServices().size();
156: }
157:
158: // Seems to try to match the url to a Georesource.
159: private IGeoResource match(Collection<IService> services, URL url,
160: IProgressMonitor monitor) throws IOException {
161:
162: // if there is no ref then the url is not matching a georesource
163: if (url.getRef() == null || url.getRef().equals("")) //$NON-NLS-1$
164: return null;
165:
166: for (IService service : services) {
167: for (IGeoResource resource : service.members(monitor)) {
168: if (resource.getIdentifier() == null)
169: continue;
170:
171: if (url.equals(resource.getIdentifier()))
172: return resource;
173: }
174: }
175:
176: return null;
177: }
178:
179: @Override
180: public String getName() {
181: return Messages.ResourceSelectionState_stateName;
182: }
183: }
|