--- /dev/null
+package org.apache.archiva.rest.api.model;
+/*
+ * 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.
+ */
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Olivier Lamy
+ * @since 1.4-M3
+ */
+@XmlRootElement( name = "browseGroupIdEntry" )
+public class BrowseGroupIdEntry
+ implements Comparable<BrowseGroupIdEntry>
+{
+
+ private String name;
+
+ private boolean project;
+
+ public BrowseGroupIdEntry()
+ {
+ // no op
+ }
+
+ public BrowseGroupIdEntry( String name, boolean project )
+ {
+ this.name = name;
+ this.project = project;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName( String name )
+ {
+ this.name = name;
+ }
+
+ public boolean isProject()
+ {
+ return project;
+ }
+
+ public void setProject( boolean project )
+ {
+ this.project = project;
+ }
+
+ public int compareTo( BrowseGroupIdEntry browseGroupIdEntry )
+ {
+ return this.name.compareTo( browseGroupIdEntry.name );
+ }
+}
--- /dev/null
+package org.apache.archiva.rest.api.model;
+/*
+ * 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.
+ */
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Olivier Lamy
+ * @since 1.4-M3
+ */
+@XmlRootElement( name = "browseGroupIdResult" )
+public class BrowseGroupIdResult
+{
+ private List<BrowseGroupIdEntry> browseGroupIdEntries;
+
+ public BrowseGroupIdResult()
+ {
+ // no op
+ }
+
+ public BrowseGroupIdResult( List<BrowseGroupIdEntry> browseGroupIdEntries )
+ {
+ // no op
+ }
+
+ public List<BrowseGroupIdEntry> getBrowseGroupIdEntries()
+ {
+ return browseGroupIdEntries == null ? Collections.<BrowseGroupIdEntry>emptyList() : browseGroupIdEntries;
+ }
+
+ public void setBrowseGroupIdEntries( List<BrowseGroupIdEntry> browseGroupIdEntries )
+ {
+ this.browseGroupIdEntries = browseGroupIdEntries;
+ }
+}
* under the License.
*/
+import org.apache.archiva.rest.api.model.BrowseGroupIdResult;
import org.apache.archiva.rest.api.model.GroupIdList;
import org.codehaus.plexus.redback.authorization.RedbackAuthorization;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
-import java.util.List;
/**
* @author Olivier Lamy
@RedbackAuthorization( noRestriction = true, noPermission = false )
GroupIdList getRootGroups()
throws ArchivaRestServiceException;
+
+ @Path( "browseGroupId/{groupId}" )
+ @GET
+ @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
+ @RedbackAuthorization( noRestriction = true, noPermission = false )
+ BrowseGroupIdResult browseGroupId(@PathParam( "groupId" ) String groupId )
+ throws ArchivaRestServiceException;
}
import org.apache.archiva.metadata.repository.MetadataResolutionException;
import org.apache.archiva.metadata.repository.MetadataResolver;
import org.apache.archiva.metadata.repository.RepositorySession;
+import org.apache.archiva.rest.api.model.BrowseGroupIdEntry;
+import org.apache.archiva.rest.api.model.BrowseGroupIdResult;
import org.apache.archiva.rest.api.model.GroupIdList;
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
import org.apache.archiva.rest.api.services.BrowseService;
return new GroupIdList( getSortedList( namespaces ) );
}
- //---------------------------
+ public BrowseGroupIdResult browseGroupId( String groupId )
+ throws ArchivaRestServiceException
+ {
+
+ List<String> selectedRepos = getObservableRepos();
+ if ( CollectionUtils.isEmpty( selectedRepos ) )
+ {
+ // FIXME 403 ???
+ return new BrowseGroupIdResult();
+ }
+
+ Set<String> projects = new LinkedHashSet<String>();
+
+ RepositorySession repositorySession = repositorySessionFactory.createSession();
+ Set<String> namespaces;
+ try
+ {
+ MetadataResolver metadataResolver = repositorySession.getResolver();
+
+ Set<String> namespacesToCollapse = new LinkedHashSet<String>();
+ for ( String repoId : selectedRepos )
+ {
+ namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
+
+ projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
+ }
+
+ // TODO: this logic should be optional, particularly remembering we want to keep this code simple
+ // it is located here to avoid the content repository implementation needing to do too much for what
+ // is essentially presentation code
+ namespaces = new LinkedHashSet<String>();
+ for ( String n : namespacesToCollapse )
+ {
+ // TODO: check performance of this
+ namespaces.add(
+ collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
+ }
+ }
+ catch ( MetadataResolutionException e )
+ {
+ throw new ArchivaRestServiceException( e.getMessage(),
+ Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
+ }
+ finally
+ {
+ repositorySession.close();
+ }
+ List<BrowseGroupIdEntry> browseGroupIdEntries =
+ new ArrayList<BrowseGroupIdEntry>( namespaces.size() + projects.size() );
+ for ( String namespace : namespaces )
+ {
+ browseGroupIdEntries.add( new BrowseGroupIdEntry( namespace, false ) );
+ }
+ for ( String project : projects )
+ {
+ browseGroupIdEntries.add( new BrowseGroupIdEntry( project, true ) );
+ }
+ Collections.sort( browseGroupIdEntries );
+ return new BrowseGroupIdResult( browseGroupIdEntries );
+
+ }
+
+//---------------------------
// internals
//---------------------------
BrowseTopViewModel=function(groupIds){
this.groupIds=groupIds;
+ displayGroupDetail=function(groupId){
+ $.log("groupId:"+groupId);
+ $.ajax("restServices/archivaServices/browseService/browseGroupId/"+encodeURIComponent(groupId), {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var groupdIds = $.map(data.groupIdList.groupIds,function(item){
+ return item;
+ });
+ $.log("size:"+groupdIds.length);
+ //var browseTopViewModel = new BrowseTopViewModel(groupdIds);
+ //ko.applyBindings(browseTopViewModel,mainContent.find("#browse_result" ).get(0));
+ }
+ });
+ }
}
displayBrowse=function(){
var mainContent = $("#main-content");
- mainContent.html(mediumSpinnerImg());
+ mainContent.html($("#browse-tmpl" ).tmpl());
+ mainContent.find("#browse_result").html(mediumSpinnerImg());
$.ajax("restServices/archivaServices/browseService/rootGroups", {
type: "GET",
dataType: 'json',
});
$.log("size:"+groupdIds.length);
var browseTopViewModel = new BrowseTopViewModel(groupdIds);
- mainContent.html($("#browse-tmpl" ).tmpl());
+
ko.applyBindings(browseTopViewModel,mainContent.find("#browse_result" ).get(0));
}
});
<h2>${$.i18n.prop('browse.groups')}</h2>
</div>
</div>
- <div id="browse_result" data-bind='template:{name:"browse-top-tmpl"}'>
+ <div id="browse_result" class="well" data-bind='template:{name:"browse-top-tmpl"}'>
</div>
</script>
<script id="browse-top-tmpl" type="text/html">
- <div class="well">
+ <div>
<ul>
{{each(i,groupId) groupIds}}
- <li class="browse-list"> ${groupId}</li>
+ <li class="browse-list">
+ <a href="#" data-bind="click: function(){displayGroupDetail(groupId)}"> ${groupId}</a>
+ </li>
{{/each}}
</ul>
</div>
}
// TODO: this logic should be optional, particularly remembering we want to keep this code simple
- // it is located here to avoid the content repository implementation needing to do too much for what
- // is essentially presentation code
+ // it is located here to avoid the content repository implementation needing to do too much for what
+ // is essentially presentation code
namespaces = new LinkedHashSet<String>();
for ( String n : namespacesToCollapse )
{