[haiku-depot-web] [haiku-depot-web-app] push by haiku.li...@xxxxxxxxx - package icon report on 2014-11-12 10:52 GMT

  • From: haiku-depot-web-app@xxxxxxxxxxxxxx
  • To: haiku-depot-web@xxxxxxxxxxxxx
  • Date: Wed, 12 Nov 2014 10:53:08 +0000

Revision: ab0407a8ba9f
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Wed Nov 12 10:52:27 2014 UTC
Log:      package icon report

https://code.google.com/p/haiku-depot-web-app/source/detail?r=ab0407a8ba9f

Added:
/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconSpreadsheetReportController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgIconConfiguration.java
Modified:
/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/MediaType.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java
 /haikudepotserver-webapp/src/main/resources/messages.properties
 /haikudepotserver-webapp/src/main/resources/messages_de.properties
 /haikudepotserver-webapp/src/main/webapp/js/app/controller/reports.html
/haikudepotserver-webapp/src/main/webapp/js/app/controller/reportscontroller.js

=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconSpreadsheetReportController.java Wed Nov 12 10:52:27 2014 UTC
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.pkg.controller;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.query.PrefetchTreeNode;
+import org.haikuos.haikudepotserver.dataobjects.Pkg;
+import org.haikuos.haikudepotserver.dataobjects.User;
+import org.haikuos.haikudepotserver.pkg.PkgOrchestrationService;
+import org.haikuos.haikudepotserver.pkg.model.PkgIconConfiguration;
+import org.haikuos.haikudepotserver.security.AuthorizationService;
+import org.haikuos.haikudepotserver.security.model.Permission;
+import org.haikuos.haikudepotserver.support.Callback;
+import org.haikuos.haikudepotserver.support.web.AbstractController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * <p>This report produces a list of icon configuration by package.</p>
+ */
+
+@Controller
+@RequestMapping("/secured/pkg/pkgiconspreadsheetreport")
+public class PkgIconSpreadsheetReportController extends AbstractController {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(PkgIconSpreadsheetReportController.class);
+
+    private static String MARKER = "*";
+
+    @Resource
+    private AuthorizationService authorizationService;
+
+    @Resource
+    private ServerRuntime serverRuntime;
+
+    @Resource
+    private PkgOrchestrationService pkgOrchestrationService;
+
+    @RequestMapping(value="download.csv", method = RequestMethod.GET)
+    public void generate(HttpServletResponse response) throws IOException {
+
+        ObjectContext context = serverRuntime.getContext();
+
+        Optional<User> user = tryObtainAuthenticatedUser(context);
+
+        if(!authorizationService.check(
+                context,
+                user.orNull(),
+                null, Permission.BULK_PKGICONSPREADSHEETREPORT)) {
+ LOGGER.warn("attempt to access a package icon spreadsheet report, but was unauthorized");
+            throw new AuthorizationFailure();
+        }
+
+        setHeadersForCsvDownload(response, "pkgiconspreadsheetreport");
+
+        final CSVWriter writer = new CSVWriter(response.getWriter(), ',');
+
+        // obtain a list of all of the possible media configurations
+
+ final List<PkgIconConfiguration> pkgIconConfigurations = pkgOrchestrationService.getInUsePkgIconConfigurations(context);
+
+        {
+            List<String> headings = Lists.newArrayList();
+
+            headings.add("pkg-name");
+            headings.add("no-icons");
+
+ for (PkgIconConfiguration pkgIconConfiguration : pkgIconConfigurations) {
+
+                StringBuilder heading = new StringBuilder();
+
+ heading.append(pkgIconConfiguration.getMediaType().getCode());
+
+                if (null != pkgIconConfiguration.getSize()) {
+                    heading.append("@");
+ heading.append(pkgIconConfiguration.getSize().toString());
+                }
+
+                headings.add(heading.toString());
+
+            }
+
+ writer.writeNext(headings.toArray(new String[headings.size()]));
+        }
+
+        // stream out the packages.
+
+        long startMs = System.currentTimeMillis();
+        LOGGER.info("will produce icon spreadsheet report");
+
+        PrefetchTreeNode prefetchTreeNode = new PrefetchTreeNode();
+        prefetchTreeNode.addPath(Pkg.PKG_ICONS_PROPERTY);
+
+ int count = pkgOrchestrationService.each(context, prefetchTreeNode, new Callback<Pkg>() {
+            @Override
+            public boolean process(Pkg pkg) {
+
+                List<String> cells = Lists.newArrayList();
+                cells.add(pkg.getName());
+
+                cells.add(pkg.getPkgIcons().isEmpty() ? MARKER : "");
+
+ for(PkgIconConfiguration pkgIconConfiguration : pkgIconConfigurations) {
+                    cells.add(
+                            pkg.getPkgIcon(
+                                    pkgIconConfiguration.getMediaType(),
+                                    pkgIconConfiguration.getSize()
+                            ).isPresent()
+                                    ? MARKER
+                                    : "");
+                }
+
+                writer.writeNext(cells.toArray(new String[cells.size()]));
+
+                return true;
+            }
+        });
+
+        LOGGER.info(
+                "did produce icon report for {} packages in {}ms",
+                count,
+                System.currentTimeMillis() - startMs);
+
+        writer.close();
+
+    }
+
+ @ResponseStatus(value= HttpStatus.UNAUTHORIZED, reason="the authenticated user is not able to run the package icon spreadsheet report")
+    public class AuthorizationFailure extends RuntimeException {}
+
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgIconConfiguration.java Wed Nov 12 10:52:27 2014 UTC
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.pkg.model;
+
+import com.google.common.base.Preconditions;
+import org.haikuos.haikudepotserver.dataobjects.MediaType;
+
+/**
+ * <p>A package icon has a media type and a size.  This model class simply
+ * combines those two together.</p>
+ */
+public class PkgIconConfiguration implements Comparable<PkgIconConfiguration> {
+
+    private MediaType mediaType;
+    private Integer size;
+
+    public PkgIconConfiguration(MediaType mediaType, Integer size) {
+ Preconditions.checkState(null!=mediaType, "the media type is required"); + Preconditions.checkState(null==size || size > 0, "illegal size value for icon configuration");
+        this.mediaType = mediaType;
+        this.size = size;
+    }
+
+    public MediaType getMediaType() {
+        return mediaType;
+    }
+
+    public Integer getSize() {
+        return size;
+    }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "%s @ %s",
+                getMediaType().getCode(),
+                getSize().toString());
+    }
+
+    @Override
+    public int compareTo(PkgIconConfiguration o) {
+ int result = o.getMediaType().getCode().compareTo(getMediaType().getCode());
+
+        if(0==result) {
+            if((null==o.getSize()) != (null==getSize())) {
+                if(null==getSize()) {
+                    result = 1;
+                }
+                else {
+                    result = -1;
+                }
+            }
+            else {
+                if(null!=getSize()) {
+                    result = o.getSize().compareTo(getSize());
+                }
+            }
+        }
+
+        return result;
+    }
+}
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/MediaType.java Mon Feb 24 08:20:27 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/MediaType.java Wed Nov 12 10:52:27 2014 UTC
@@ -11,7 +11,9 @@
 import com.google.common.collect.Iterables;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.query.Ordering;
 import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.SortOrder;
 import org.haikuos.haikudepotserver.dataobjects.auto._MediaType;

 import java.util.List;
@@ -24,6 +26,13 @@

     public final static String EXTENSION_PNG = "png";

+    public static List<MediaType> getAll(ObjectContext context) {
+        Preconditions.checkNotNull(context);
+        SelectQuery query = new SelectQuery(MediaType.class);
+ query.addOrdering(new Ordering(CODE_PROPERTY, SortOrder.ASCENDING));
+        return (List<MediaType>) context.performQuery(query);
+    }
+
     /**
* <p>Files can have extensions that help to signify what sort of files they are. For example, a PNG file would * have the extension "png". This method will be able to return a media type for a given file extension.</p>
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java Sat Oct 25 20:54:51 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java Wed Nov 12 10:52:27 2014 UTC
@@ -5,10 +5,7 @@

 package org.haikuos.haikudepotserver.pkg;

-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
+import com.google.common.base.*;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -19,10 +16,7 @@
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.query.*;
 import org.haikuos.haikudepotserver.dataobjects.*;
-import org.haikuos.haikudepotserver.pkg.model.BadPkgIconException;
-import org.haikuos.haikudepotserver.pkg.model.BadPkgScreenshotException;
-import org.haikuos.haikudepotserver.pkg.model.PkgSearchSpecification;
-import org.haikuos.haikudepotserver.pkg.model.SizeLimitReachedException;
+import org.haikuos.haikudepotserver.pkg.model.*;
 import org.haikuos.haikudepotserver.support.Callback;
 import org.haikuos.haikudepotserver.support.ImageHelper;
 import org.haikuos.haikudepotserver.support.VersionCoordinates;
@@ -38,10 +32,7 @@
 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
 import java.io.*;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;

 /**
  * <p>This service undertakes non-trivial operations on packages.</p>
@@ -478,6 +469,79 @@

         return pkgIconOptional.get();
     }
+
+ private List<MediaType> getInUsePkgIconMediaTypes(final ObjectContext context) {
+        StringBuilder queryString = new StringBuilder();
+
+        queryString.append("SELECT ");
+        queryString.append(" DISTINCT pi.");
+ queryString.append(PkgIcon.MEDIA_TYPE_PROPERTY + "." + MediaType.CODE_PROPERTY);
+        queryString.append(" FROM ");
+        queryString.append(PkgIcon.class.getSimpleName());
+        queryString.append(" pi");
+
+        EJBQLQuery query = new EJBQLQuery(queryString.toString());
+
+        final List<String> codes = context.performQuery(query);
+
+        return Lists.transform(
+                codes,
+                new Function<String, MediaType>() {
+                    @Override
+                    public MediaType apply(String input) {
+                        return MediaType.getByCode(context, input).get();
+                    }
+                }
+        );
+
+    }
+
+ private List<Integer> getInUsePkgIconSizes(ObjectContext context, MediaType mediaType) {
+        StringBuilder queryString = new StringBuilder();
+
+        queryString.append("SELECT ");
+        queryString.append(" DISTINCT pi.");
+        queryString.append(PkgIcon.SIZE_PROPERTY);
+        queryString.append(" FROM ");
+        queryString.append(PkgIcon.class.getSimpleName());
+        queryString.append(" pi WHERE pi.");
+        queryString.append(PkgIcon.MEDIA_TYPE_PROPERTY);
+        queryString.append(" = :mediaType");
+
+        EJBQLQuery query = new EJBQLQuery(queryString.toString());
+        query.setParameter("mediaType", mediaType);
+
+        return (List<Integer>) context.performQuery(query);
+    }
+
+    /**
+ * <p>The packages are configured with icons. Each icon has a media type and, + * optionally a size. This method will return all of those possible media + * type + size combinations that are actually in use at the moment. The list
+     * will be unique.</p>
+     */
+
+ public List<PkgIconConfiguration> getInUsePkgIconConfigurations(ObjectContext objectContext) { + Preconditions.checkState(null!=objectContext,"the object context must be supplied");
+        List<PkgIconConfiguration> result = Lists.newArrayList();
+
+ for(MediaType mediaType : getInUsePkgIconMediaTypes(objectContext)) { + List<Integer> sizes = getInUsePkgIconSizes(objectContext, mediaType);
+
+            if(sizes.isEmpty()) {
+                result.add(new PkgIconConfiguration(mediaType, null));
+            }
+            else {
+                for(Integer size : sizes) {
+                    result.add(new PkgIconConfiguration(mediaType, size));
+                }
+            }
+        }
+
+        Collections.sort(result);
+
+        return result;
+    }

     // ------------------------------
     // SCREENSHOT
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java Tue Nov 11 00:02:22 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java Wed Nov 12 10:52:27 2014 UTC
@@ -214,6 +214,7 @@
return null!=authenticatedUser && authenticatedUser.getIsRoot();

             case BULK_PKGPROMINENCESPREADSHEETREPORT:
+            case BULK_PKGICONSPREADSHEETREPORT:
             case BULK_PKGCATEGORYCOVERAGESPREADSHEETREPORT:
                 return null!=authenticatedUser;

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java Tue Nov 11 00:02:22 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java Wed Nov 12 10:52:27 2014 UTC
@@ -33,7 +33,8 @@
     PKG_EDITPROMINENCE(TargetType.PKG),

     BULK_PKGCATEGORYCOVERAGESPREADSHEETREPORT(null),
-    BULK_PKGPROMINENCESPREADSHEETREPORT(null);
+    BULK_PKGPROMINENCESPREADSHEETREPORT(null),
+    BULK_PKGICONSPREADSHEETREPORT(null);

     private TargetType requiredTargetType;

=======================================
--- /haikudepotserver-webapp/src/main/resources/messages.properties Tue Nov 11 00:02:22 2014 UTC +++ /haikudepotserver-webapp/src/main/resources/messages.properties Wed Nov 12 10:52:27 2014 UTC
@@ -388,6 +388,7 @@

reporting.pkgcategorycoveragespreadsheetreport.title=Package category coverage report
 reporting.pkgprominencespreadsheetreport.title=Package prominence report
+reporting.pkgiconspreadsheetreport.title=Package icon report

 # Multipage (non-AngularJS) Interface
 multipage.banner.title.suffix=Simple
=======================================
--- /haikudepotserver-webapp/src/main/resources/messages_de.properties Tue Nov 11 00:02:22 2014 UTC +++ /haikudepotserver-webapp/src/main/resources/messages_de.properties Wed Nov 12 10:52:27 2014 UTC
@@ -382,6 +382,7 @@

reporting.pkgcategorycoveragespreadsheetreport.title=Verteilung der Pakete nach Kategorien
 reporting.pkgprominencespreadsheetreport.title=Empfehlungsstufen der Pakete
+reporting.pkgiconspreadsheetreport.title=Icons der Pakete

 # Multipage (non-AngularJS) Interface
 multipage.banner.title.suffix=Einfach
=======================================
--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/reports.html Tue Nov 11 00:02:22 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/reports.html Wed Nov 12 10:52:27 2014 UTC
@@ -12,6 +12,11 @@
             <a href="" ng-click="goPkgProminenceSpreadsheetReport()">
<message key="reporting.pkgprominencespreadsheetreport.title"></message>
             </a>
+        </li>
+        <li show-if-permission="'BULK_PKGICONSPREADSHEETREPORT'">
+            <a href="" ng-click="goPkgIconSpreadsheetReport()">
+ <message key="reporting.pkgiconspreadsheetreport.title"></message>
+            </a>
         </li>
     </ul>

=======================================
--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/reportscontroller.js Tue Nov 11 00:02:22 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/reportscontroller.js Wed Nov 12 10:52:27 2014 UTC
@@ -19,22 +19,26 @@

// the random aspect here is so that it is unlikely to cache the result.

-            $scope.goPkgCategoryCoverageSpreadsheetReport = function() {
+            function goSecuredCsvReport(pathPart) {
                 var iframeEl = document.getElementById("download-iframe");
- iframeEl.src = '/secured/pkg/pkgcategorycoveragespreadsheetreport/download.csv?hdsbtok=' +
-                    userState.user().token +
-                    '&rnd=' +
-                    _.random(0,1000);
-            }
-
-            $scope.goPkgProminenceSpreadsheetReport = function() {
-                var iframeEl = document.getElementById("download-iframe");
- iframeEl.src = '/secured/pkg/pkgprominencespreadsheetreport/download.csv?hdsbtok=' + + iframeEl.src = '/secured/'+pathPart+'/download.csv?hdsbtok=' +
                 userState.user().token +
                 '&rnd=' +
                 _.random(0,1000);
             }

+            $scope.goPkgCategoryCoverageSpreadsheetReport = function() {
+ goSecuredCsvReport('pkg/pkgcategorycoveragespreadsheetreport');
+            };
+
+            $scope.goPkgProminenceSpreadsheetReport = function() {
+                goSecuredCsvReport('pkg/pkgprominencespreadsheetreport');
+            };
+
+            $scope.goPkgIconSpreadsheetReport = function() {
+                goSecuredCsvReport('pkg/pkgiconspreadsheetreport');
+            };
+
         }
     ]
 );

Other related posts:

  • » [haiku-depot-web] [haiku-depot-web-app] push by haiku.li...@xxxxxxxxx - package icon report on 2014-11-12 10:52 GMT - haiku-depot-web-app