### Google+ albums

The information about Google albums (name, cover photo, …) is retrieved when user signs in with Google. When the user clicks on an album and the images aren't available locally, they are downloaded from google and save to a bean (GooglePlusAlbumCache.java).

                <a4j:commandLink execute="@this"
                    onclick="#{'#{'}googlePlusAlbumCache.isAlbumLoaded(albumId)} ? loadAlbum('#{'#{'}albumId}') : G.getImages('#{'#{'}albumId}', loadPhotos)">
                    <h:graphicImage id="img" url="#{'#{'}googlePlusAlbumCache.getAlbum(albumId).getString('coverUrl')}"
                        style="max-width: 120px; max-height: 120px" styleClass="album-cover-image" />
                    <rich:tooltip followMouse="true" direction="topRight" showDelay="500" styleClass="tooltip">
                        <span style="white-space: nowrap">
                            #{'#{'}googlePlusAlbumCache.getAlbum(albumId).getString("name")} </span>
                    </rich:tooltip>
                    <rich:dragSource dragIndicator="dragIndicator" type="gAlbum"
                        dragValue="#{'#{'}googlePlusAlbumCache.getAlbum(albumId).getString('fullId')}" />
                </a4j:commandLink>

                    …

                <a4j:jsFunction name="loadPhotos" execute="@this" actionListener="#{'#{'}controller.showGPlusAlbum()}" oncomplete="reload()">
                    <a4j:param assignTo="#{'#{'}googlePlusAlbumCache.albumImages}" name="response" />
                </a4j:jsFunction>

                <a4j:jsFunction name="loadAlbum" execute="@this" actionListener="#{'#{'}controller.showGPlusAlbum()}" oncomplete="reload()">
                    <a4j:param assignTo="#{'#{'}googlePlusAlbumCache.currentAlbumId}" name="response" />
                </a4j:jsFunction>

### Sharing and importing

The user can drag and drop his albums into events and is given the choice to:

- Share the album: images will be still displayed from Google
- Import the album: images will be downloaded and saved into Photoalbum

                <h:panelGrid columns="2" style="margin-left: auto; margin-right: auto; height: 60px">
                    <h:panelGroup layout="block">
                        <richx:commandButton value="Import" execute="@this" styleClass="shelf"
                            disabled="#{'#{'}gDndManager.albumAlreadyShared}"
                            onclick="G.getImages('#{'#{'}gDndManager.album.getString('fullId')}', fetchPhotosForImport)" render="gBar" />
                    </h:panelGroup>
                    <h:panelGroup layout="block">
                        <richx:commandButton oncomplete="#{'#{'}rich:component('gAlbumModalPanel')}.hide();" value="Just Share"
                            disabled="#{'#{'}gDndManager.albumAlreadyShared}" actionListener="#{'#{'}gDndManager.shareAlbum()}"
                            execute="@this" styleClass="shelf" />
                    </h:panelGroup>
                </h:panelGrid>

Sharing an album will simply save the album's id in the event.

                public void shareAlbum() {
                    event.getRemoteAlbumIds().add("G" + albumId);

                    try {
                        ea.editEvent(event);
                    } catch (PhotoAlbumException pae) {
                        error.fire(new ErrorEvent("Error saving event", pae.getMessage()));
                    }
                }

Importing is done by rich:progressBar that polls the images and saves them in the database one by one.

            <a4j:jsFunction name="startImport" actionListener="#{'#{'}gDndManager.importAlbum()}"
                oncomplete="#{'#{'}rich:component('gAlbumModalPanel')}.hide();" render="gBar" />

            <a4j:jsFunction name="fetchPhotosForImport" oncomplete="startImport()">
                <a4j:param assignTo="#{'#{'}googlePlusAlbumCache.albumImages}" name="images" />
            </a4j:jsFunction>

                …

            <rich:progressBar id="gBar" value="#{'#{'}fileDownloadManager.value}" minValue="0" maxValue="100"
                enabled="#{'#{'}fileDownloadManager.hasNext()}" interval="1000">
                <f:facet name="initial">
                    <h:outputText value="" />
                </f:facet>
                <h:outputText value="Importing #{'#{'}fileDownloadManager.text}" />
                <a4j:ajax event="begin" listener="#{'#{'}fileDownloadManager.downloadNext()}" />
                <a4j:ajax event="finish" oncomplete="finishImport()" />
            </rich:progressBar>

The `importAlbum()` method retrieves the images from Google and creates a new album in the target event. It then starts the poll. `FileUploadManager.java` takes care of the uploading:

            public void downloadNext() {
                if (!hasNext()) {
                    return;
                }
                String imageUrl = iterator.next();

                uploadImage(imageUrl, album.getName() + imageUrl.substring(imageUrl.lastIndexOf(Constants.DOT)), album);
                count++;
                pBarValue = (count * 100) / size;
                pBarText = count + " / " + size;
            }

            private void uploadImage(String imageUrl, String imageName, Album album) {
                File file = new File(imageName);
                int i;
                try {
                    URL url = new URL(imageUrl);
                    URLConnection con = url.openConnection();
                    BufferedInputStream bis = new BufferedInputStream(con.getInputStream());
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file.getName()));
                    while ((i = bis.read()) != -1) {
                        bos.write(i);
                    }
                    bos.flush();
                    bis.close();
                } catch (MalformedInputException malformedInputException) {
                    error.fire(new ErrorEvent("Error", "error uploading image<br/>" + malformedInputException.getMessage()));
                } catch (IOException ioException) {
                    error.fire(new ErrorEvent("Error", "IO error<br/>" + ioException.getMessage()));
                }

                fileUploadManager.uploadFile(new FileHandler(file), album);
            }