├── .gitignore
├── CODEOWNERS
├── google393c719b8636389e.html
├── google_dicom_explorer.png
├── src
├── main
│ ├── resources
│ │ ├── loading.gif
│ │ └── client_secrets.json
│ └── java
│ │ └── org
│ │ └── weasis
│ │ └── dicom
│ │ └── google
│ │ ├── explorer
│ │ ├── messages.properties
│ │ ├── internal
│ │ │ └── Activator.java
│ │ ├── Messages.java
│ │ ├── GoogleDicomExplorerFactory.java
│ │ ├── GoogleDicomExplorer.java
│ │ └── DownloadManager.java
│ │ └── api
│ │ ├── ui
│ │ ├── dicomstore
│ │ │ ├── StoreUpdateListener.java
│ │ │ ├── StoreUpdateEvent.java
│ │ │ ├── LoadDatasetsTask.java
│ │ │ ├── LoadDicomStoresTask.java
│ │ │ ├── LoadLocationsTask.java
│ │ │ ├── LoadProjectsTask.java
│ │ │ ├── AbstractDicomSelectorTask.java
│ │ │ ├── AutoRefreshComboBoxExtension.java
│ │ │ ├── GoogleLoginTask.java
│ │ │ ├── LoadStudiesTask.java
│ │ │ └── DicomStoreSelector.java
│ │ ├── NavigationPanel.java
│ │ ├── GoogleExplorer.java
│ │ ├── StudyView.java
│ │ ├── OAuth2Browser.java
│ │ ├── StudiesTable.java
│ │ └── SearchPanel.java
│ │ ├── GoogleAPIClientFactory.java
│ │ ├── model
│ │ ├── ProjectDescriptor.java
│ │ ├── Dataset.java
│ │ ├── DicomStore.java
│ │ ├── Location.java
│ │ ├── StudyQuery.java
│ │ └── StudyModel.java
│ │ ├── util
│ │ └── StringUtils.java
│ │ └── GoogleAPIClient.java
└── test
│ └── java
│ └── org
│ └── weasis
│ └── dicom
│ └── google
│ └── api
│ └── GoogleAPIClientTest.java
├── cloudbuild.yaml
├── release
├── githubRelease.yaml
└── githubRelease.sh
├── CONTRIBUTING.md
├── README.md
├── pom.xml
└── LICENSE.md
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | /.settings/
3 | /.classpath
4 | /.project
5 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @poojavenkatram
2 | * @danielbeaudreau
3 | * @sbabitz
4 |
--------------------------------------------------------------------------------
/google393c719b8636389e.html:
--------------------------------------------------------------------------------
1 | google-site-verification: google393c719b8636389e.html
--------------------------------------------------------------------------------
/google_dicom_explorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/weasis-chcapi-extension/HEAD/google_dicom_explorer.png
--------------------------------------------------------------------------------
/src/main/resources/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/weasis-chcapi-extension/HEAD/src/main/resources/loading.gif
--------------------------------------------------------------------------------
/src/main/resources/client_secrets.json:
--------------------------------------------------------------------------------
1 | {"installed":{"client_id":"952621265781-q7lsqhhths8jp5k124nqj7qo1la92ps5.apps.googleusercontent.com","project_id":"chc-github-weasis-ext","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"NlHxVP2X3OimN4DS4o09OxGz","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
--------------------------------------------------------------------------------
/cloudbuild.yaml:
--------------------------------------------------------------------------------
1 | steps:
2 | - name: "gcr.io/cloud-builders/git"
3 | args:
4 | - "clone"
5 | - "https://github.com/nroduit/Weasis.git"
6 | - "weasis"
7 | - name: "gcr.io/cloud-builders/git"
8 | args:
9 | - "checkout"
10 | - "tags/v3.6.0"
11 | dir: "weasis"
12 | - name: "maven:3.6.3-jdk-14"
13 | volumes:
14 | - name: "mavenLocal"
15 | path: "/root/.m2"
16 | args:
17 | - "mvn"
18 | - "install"
19 | dir: "weasis"
20 | - name: "maven:3.6.3-jdk-14"
21 | volumes:
22 | - name: "mavenLocal"
23 | path: "/root/.m2"
24 | args:
25 | - "mvn"
26 | - "install"
27 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/explorer/messages.properties:
--------------------------------------------------------------------------------
1 |
2 | GoogleDicomExplorer.title=GOOGLEDICOM
3 | GoogleDicomExplorer.btn_title=Google Healthcare Explorer
4 | GoogleDicomExplorer.desc=Explore Google Healthcare Dicom data
5 | DicomStoreSelector.sign_in=Google Sign In
6 | DicomStoreSelector.sign_out=Google Sign Out
7 | DicomStoreSelector.default_project_text=-- Choose or type project --
8 | DicomStoreSelector.default_location_text=-- Choose location --
9 | DicomStoreSelector.default_dataset_text=-- Choose dataset --
10 | DicomStoreSelector.default_dicomstore_text=-- Choose store --
11 | GoogleAPIClient.open_browser_message=The system cannot open your default browser to authorize.\nAuthorization URL has been copied to clipboard.\nPlease paste it in your browser and follow instructions.
12 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/StoreUpdateListener.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import java.util.EventListener;
18 | /** Listener for DICOM store updates
19 | */
20 | public interface StoreUpdateListener extends EventListener {
21 | void actionPerformed(StoreUpdateEvent event);
22 | }
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/explorer/internal/Activator.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.explorer.internal;
16 |
17 | import org.osgi.framework.BundleActivator;
18 | import org.osgi.framework.BundleContext;
19 |
20 | public class Activator implements BundleActivator {
21 |
22 |
23 | @Override
24 | public void start(final BundleContext context) {
25 |
26 | }
27 |
28 | @Override
29 | public void stop(BundleContext context) {
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/release/githubRelease.yaml:
--------------------------------------------------------------------------------
1 | steps:
2 | - name: "gcr.io/cloud-builders/git"
3 | args:
4 | - "clone"
5 | - "https://github.com/nroduit/Weasis.git"
6 | - "weasis"
7 | - name: "gcr.io/cloud-builders/git"
8 | args:
9 | - "checkout"
10 | - "tags/v3.6.0"
11 | dir: "weasis"
12 | - name: "maven:3.6.3-jdk-14"
13 | volumes:
14 | - name: "mavenLocal"
15 | path: "/root/.m2"
16 | args:
17 | - "mvn"
18 | - "install"
19 | dir: "weasis"
20 | - name: "maven:3.6.3-jdk-14"
21 | volumes:
22 | - name: "mavenLocal"
23 | path: "/root/.m2"
24 | args:
25 | - "mvn"
26 | - "install"
27 | - name: 'google/cloud-sdk:290.0.1'
28 | args:
29 | - 'bash'
30 | - './release/githubRelease.sh'
31 | - '$REPO_NAME'
32 | - '$TAG_NAME'
33 | secretEnv:
34 | - 'ACCESS_TOKEN'
35 | timeout: 600s
36 | secrets:
37 | - kmsKeyName: projects/gcp-healthcare-oss-test/locations/global/keyRings/default/cryptoKeys/github-robot-access-token
38 | secretEnv:
39 | ACCESS_TOKEN: CiQAM/SK3FUc1t+CnHDdgRzbc556FIyHddxRpsnolmSKfpiZ66sSUQDrEGO9gz15JIulryNagWzUOGbBEAaC04y85J8fNRjJZ8T8ntzh6Kt0Sa+GCG+3n5xSQdDJdj6xOG0LfVzvU+/K3mZ1KJlIcd0jiCeBrjYLlw==
40 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/StoreUpdateEvent.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package org.weasis.dicom.google.api.ui.dicomstore;
15 |
16 | import java.awt.AWTEvent;
17 |
18 | /** DICOM store update event to notify listeners
19 | */
20 | public class StoreUpdateEvent extends AWTEvent {
21 | static int id;
22 |
23 | /** Creates a StoreUpdateEvent with the source object and a unique id
24 | * @return Store update event.
25 | */
26 | public StoreUpdateEvent(Object source) {
27 | super(source, id++);
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution;
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
25 | ## Community Guidelines
26 |
27 | This project follows
28 | [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
29 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/GoogleAPIClientFactory.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api;
16 |
17 | public class GoogleAPIClientFactory {
18 |
19 | private static GoogleAPIClientFactory instance;
20 |
21 | private GoogleAPIClient googleAPIClient;
22 |
23 | public static GoogleAPIClientFactory getInstance() {
24 | if (instance == null) {
25 | instance = new GoogleAPIClientFactory();
26 | }
27 | return instance;
28 | }
29 |
30 | public GoogleAPIClient createGoogleClient() {
31 | if (googleAPIClient == null) {
32 | googleAPIClient = new GoogleAPIClient();
33 | }
34 | return googleAPIClient;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/explorer/Messages.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.explorer;
16 |
17 | import java.util.MissingResourceException;
18 | import java.util.ResourceBundle;
19 |
20 | public class Messages {
21 | private static final String BUNDLE_NAME = "org.weasis.dicom.google.explorer.messages"; //$NON-NLS-1$
22 |
23 | private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
24 |
25 | private Messages() {
26 | }
27 |
28 | public static String getString(String key) {
29 | try {
30 | return RESOURCE_BUNDLE.getString(key);
31 | } catch (MissingResourceException e) {
32 | return '!' + key + '!';
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/NavigationPanel.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package org.weasis.dicom.google.api.ui;
15 |
16 | import javax.swing.JButton;
17 | import javax.swing.JLabel;
18 | import javax.swing.JPanel;
19 | import java.awt.FlowLayout;
20 |
21 | /** Panel to combine and align navigation buttons relative to searchPanel
22 | */
23 | public class NavigationPanel extends JPanel {
24 | private SearchPanel searchPanel;
25 |
26 | public NavigationPanel(SearchPanel searchPanel) {
27 | this.searchPanel = searchPanel;
28 | JButton previousButton = searchPanel.getPageNumberButtonPrevious();
29 | JButton nextButton = searchPanel.getPageNumberButtonNext();
30 | JLabel pageNumberLabel = searchPanel.getPageNumberLabel();
31 | this.setLayout(new FlowLayout(FlowLayout.LEFT));
32 | this.add(previousButton);
33 | this.add(pageNumberLabel);
34 | this.add(nextButton);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/model/ProjectDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.model;
16 |
17 | import java.util.Objects;
18 |
19 | public class ProjectDescriptor {
20 |
21 | private final String name;
22 | private final String id;
23 |
24 | public ProjectDescriptor(String name, String id) {
25 | this.name = name;
26 | this.id = id;
27 | }
28 |
29 | public String getName() {
30 | return name;
31 | }
32 |
33 | public String getId() {
34 | return id;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return name;
40 | }
41 |
42 | @Override
43 | public boolean equals(Object o) {
44 | if (this == o) return true;
45 | if (o == null || getClass() != o.getClass()) return false;
46 | ProjectDescriptor that = (ProjectDescriptor) o;
47 | return Objects.equals(name, that.name) &&
48 | Objects.equals(id, that.id);
49 | }
50 |
51 | @Override
52 | public int hashCode() {
53 | return Objects.hash(name, id);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/model/Dataset.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.model;
16 |
17 | import java.util.Objects;
18 |
19 | public class Dataset {
20 |
21 | private Location parent;
22 |
23 | private final String name;
24 |
25 | public Dataset(Location parent, String name) {
26 | this.parent = parent;
27 | this.name = name;
28 | }
29 |
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public Location getParent() {
35 | return parent;
36 | }
37 |
38 | public ProjectDescriptor getProject() {
39 | return parent.getParent();
40 | }
41 |
42 | @Override
43 | public boolean equals(Object o) {
44 | if (this == o) return true;
45 | if (o == null || getClass() != o.getClass()) return false;
46 | Dataset dataset = (Dataset) o;
47 | return Objects.equals(parent, dataset.parent) &&
48 | Objects.equals(name, dataset.name);
49 | }
50 |
51 | @Override
52 | public int hashCode() {
53 | return Objects.hash(parent, name);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/LoadDatasetsTask.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import org.weasis.dicom.google.api.GoogleAPIClient;
18 | import org.weasis.dicom.google.api.model.Dataset;
19 | import org.weasis.dicom.google.api.model.Location;
20 |
21 | import java.util.Comparator;
22 | import java.util.List;
23 |
24 | public class LoadDatasetsTask extends AbstractDicomSelectorTask> {
25 |
26 | private final Location location;
27 |
28 | public LoadDatasetsTask(Location location,
29 | GoogleAPIClient api,
30 | DicomStoreSelector view) {
31 | super(api, view);
32 | this.location = location;
33 | }
34 |
35 | @Override
36 | protected List doInBackground() throws Exception {
37 | List locations = api.fetchDatasets(location);
38 | locations.sort(Comparator.comparing(Dataset::getName));
39 | return locations;
40 | }
41 |
42 | @Override
43 | protected void onCompleted(List result) {
44 | view.updateDatasets(result);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/util/StringUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.util;
16 |
17 | import java.io.UnsupportedEncodingException;
18 | import java.net.URLEncoder;
19 | import java.util.Collection;
20 |
21 | public final class StringUtils {
22 |
23 | private StringUtils() {
24 | }
25 |
26 | public static boolean isNotBlank(String str) {
27 | return str != null
28 | && !str.trim().isEmpty();
29 | }
30 |
31 | public static String urlEncode(String str) {
32 | try {
33 | return URLEncoder.encode(str, "UTF-8");
34 | } catch (UnsupportedEncodingException ex) {
35 | throw new IllegalStateException("Error on encoding url " + str, ex);
36 | }
37 | }
38 |
39 | public static String join(Collection collection, String joinString) {
40 | StringBuilder builder = new StringBuilder();
41 | for (String str : collection) {
42 | if (builder.length() > 0) {
43 | builder.append(joinString);
44 | }
45 | builder.append(str);
46 | }
47 |
48 | return builder.toString();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/LoadDicomStoresTask.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import org.weasis.dicom.google.api.GoogleAPIClient;
18 | import org.weasis.dicom.google.api.model.Dataset;
19 | import org.weasis.dicom.google.api.model.DicomStore;
20 |
21 | import java.util.Comparator;
22 | import java.util.List;
23 |
24 | public class LoadDicomStoresTask extends AbstractDicomSelectorTask> {
25 |
26 | private final Dataset dataset;
27 |
28 | public LoadDicomStoresTask(Dataset dataset,
29 | GoogleAPIClient api,
30 | DicomStoreSelector view) {
31 | super(api, view);
32 | this.dataset = dataset;
33 | }
34 |
35 | @Override
36 | protected List doInBackground() throws Exception {
37 | List locations = api.fetchDicomstores(dataset);
38 | locations.sort(Comparator.comparing(DicomStore::getName));
39 | return locations;
40 | }
41 |
42 | @Override
43 | protected void onCompleted(List result) {
44 | view.updateDicomStores(result);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/LoadLocationsTask.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import org.weasis.dicom.google.api.GoogleAPIClient;
18 | import org.weasis.dicom.google.api.model.Location;
19 | import org.weasis.dicom.google.api.model.ProjectDescriptor;
20 |
21 | import java.util.Comparator;
22 | import java.util.List;
23 |
24 | public class LoadLocationsTask extends AbstractDicomSelectorTask> {
25 |
26 | private final ProjectDescriptor project;
27 |
28 | public LoadLocationsTask(ProjectDescriptor project,
29 | GoogleAPIClient api,
30 | DicomStoreSelector view) {
31 | super(api, view);
32 | this.project = project;
33 | }
34 |
35 | @Override
36 | protected List doInBackground() throws Exception {
37 | List locations = api.fetchLocations(project);
38 | locations.sort(Comparator.comparing(Location::getName));
39 | return locations;
40 | }
41 |
42 | @Override
43 | protected void onCompleted(List result) {
44 | view.updateLocations(result);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/LoadProjectsTask.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import org.weasis.dicom.google.api.GoogleAPIClient;
18 | import org.weasis.dicom.google.api.model.ProjectDescriptor;
19 | import org.slf4j.Logger;
20 | import org.slf4j.LoggerFactory;
21 |
22 | import java.util.Comparator;
23 | import java.util.List;
24 |
25 | public class LoadProjectsTask extends AbstractDicomSelectorTask> {
26 | private static final Logger LOGGER = LoggerFactory.getLogger(LoadProjectsTask.class);
27 |
28 | public LoadProjectsTask(GoogleAPIClient api, DicomStoreSelector view) {
29 | super(api, view);
30 | }
31 |
32 | @Override
33 | protected List doInBackground() throws Exception {
34 | List projects = api.fetchProjects();
35 | projects.sort(Comparator.comparing(ProjectDescriptor::getName));
36 | return projects;
37 | }
38 |
39 | @Override
40 | protected void onCompleted(List result) {
41 | LOGGER.debug("Loaded projects list " + result);
42 | view.updateProjects(result);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/model/DicomStore.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.model;
16 |
17 | import java.util.Objects;
18 |
19 | public class DicomStore {
20 |
21 | private final Dataset parent;
22 |
23 | private final String name;
24 |
25 | public DicomStore(Dataset parent, String name) {
26 | this.parent = parent;
27 | this.name = name;
28 | }
29 |
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public Dataset getParent() {
35 | return parent;
36 | }
37 |
38 | public ProjectDescriptor getProject() {
39 | return parent.getProject();
40 | }
41 |
42 | public Location getLocation() {
43 | return parent.getParent();
44 | }
45 |
46 | @Override
47 | public boolean equals(Object o) {
48 | if (this == o) return true;
49 | if (o == null || getClass() != o.getClass()) return false;
50 | DicomStore that = (DicomStore) o;
51 | return Objects.equals(parent, that.parent) &&
52 | Objects.equals(name, that.name);
53 | }
54 |
55 | @Override
56 | public int hashCode() {
57 | return Objects.hash(parent, name);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/model/Location.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.model;
16 |
17 | import java.util.Objects;
18 |
19 | public class Location {
20 |
21 | private final ProjectDescriptor parent;
22 |
23 | private final String name;
24 | private final String id;
25 |
26 | public Location(ProjectDescriptor parent, String name, String id) {
27 | this.parent = parent;
28 | this.name = name;
29 | this.id = id;
30 | }
31 |
32 | public String getName() {
33 | return name;
34 | }
35 |
36 | public String getId() {
37 | return id;
38 | }
39 |
40 | public ProjectDescriptor getParent() {
41 | return parent;
42 | }
43 |
44 | @Override
45 | public String toString() {
46 | return id;
47 | }
48 |
49 | @Override
50 | public boolean equals(Object o) {
51 | if (this == o) return true;
52 | if (o == null || getClass() != o.getClass()) return false;
53 | Location location = (Location) o;
54 | return Objects.equals(parent, location.parent) &&
55 | Objects.equals(name, location.name) &&
56 | Objects.equals(id, location.id);
57 | }
58 |
59 | @Override
60 | public int hashCode() {
61 | return Objects.hash(parent, name, id);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/AbstractDicomSelectorTask.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import org.weasis.dicom.google.api.GoogleAPIClient;
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 |
21 | import javax.swing.SwingWorker;
22 | import javax.swing.JOptionPane;
23 | import java.util.concurrent.ExecutionException;
24 |
25 | public abstract class AbstractDicomSelectorTask extends SwingWorker {
26 | private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDicomSelectorTask.class);
27 |
28 | protected final GoogleAPIClient api;
29 | protected final DicomStoreSelector view;
30 |
31 | public AbstractDicomSelectorTask(GoogleAPIClient api, DicomStoreSelector view) {
32 | this.api = api;
33 | this.view = view;
34 | }
35 |
36 | @Override
37 | protected final void done() {
38 | try {
39 | T result = get();
40 | onCompleted(result);
41 | } catch (ExecutionException ex) {
42 | LOGGER.error("Error on dicom task", ex.getCause());
43 | JOptionPane.showMessageDialog(null, ex.getCause().getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
44 | } catch (InterruptedException ex) {
45 | LOGGER.error("Interrupted", ex);
46 | }
47 | }
48 |
49 | protected abstract void onCompleted(T result);
50 | }
51 |
--------------------------------------------------------------------------------
/release/githubRelease.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2019 Google LLC
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | readonly REPO_NAME="${1}"
18 | readonly TAG_NAME="${2}"
19 | readonly TOKEN="${ACCESS_TOKEN}"
20 | # Get GitHub user and GitHub repo from REPO_NAME
21 | IFS='_' read -ra array <<< "${REPO_NAME}"
22 | github_user="${array[1]}"
23 | github_repo="${array[2]}"
24 | if [[ -z "${github_user}" ]]
25 | then
26 | github_user="GoogleCloudPlatform"
27 | github_repo="${REPO_NAME}"
28 | fi
29 | # Create request.json with request parameters
30 | echo "{\"tag_name\": \"${TAG_NAME}\",\"name\": \"${TAG_NAME}\"}" > request.json
31 | # Create a request for creating a release on GitHub page
32 | readonly resp_file="response.json"
33 | response_code="$(curl -# -X POST \
34 | -H "Authorization: Bearer ${TOKEN}" \
35 | -H "Content-Type:application/json" \
36 | -H "Accept:application/json" \
37 | -w "%{http_code}" \
38 | --data-binary "@/workspace/request.json" \
39 | "https://api.github.com/repos/${github_user}/${github_repo}/releases" \
40 | -o "${resp_file}")"
41 | # Check status code
42 | if [[ "${response_code}" != 201 ]]; then
43 | cat "${resp_file}"
44 | exit 1
45 | fi
46 | # Get release id from response.json
47 | release_id="$(grep -wm 1 "id" /workspace/response.json \
48 | | grep -Eo "[[:digit:]]+")"
49 | # Get JAR version from pom.xml
50 | jar_version="$(grep -m 1 "" /workspace/pom.xml \
51 | | grep -Eo "[[:digit:]]+.[[:digit:]]+.[[:digit:]]+")"
52 | jar_name="weasis-chcapi-extension-${jar_version}.jar"
53 | # Upload JAR to GitHub releases page
54 | response_code="$(curl -# -X POST -H "Authorization: token ${TOKEN}" \
55 | -H "Content-Type:application/octet-stream" \
56 | -w "%{http_code}" \
57 | --data-binary "@/workspace/target/${jar_name}" \
58 | "https://uploads.github.com/repos/${github_user}/${github_repo}/releases/${release_id}/assets?name=${jar_name}" \
59 | -o "${resp_file}")"
60 | # Check status code
61 | if [[ "${response_code}" != 201 ]]; then
62 | cat "${resp_file}"
63 | exit 2
64 | fi
65 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/explorer/GoogleDicomExplorerFactory.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.explorer;
16 |
17 | import org.osgi.service.component.ComponentContext;
18 | import org.osgi.service.component.annotations.Activate;
19 | import org.osgi.service.component.annotations.Deactivate;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 | import org.weasis.core.api.explorer.DataExplorerView;
23 | import org.weasis.core.api.explorer.DataExplorerViewFactory;
24 | import org.weasis.core.api.explorer.ObservableEvent;
25 | import org.weasis.core.ui.editor.ViewerPluginBuilder;
26 |
27 | import java.util.Hashtable;
28 |
29 | @org.osgi.service.component.annotations.Component(service = DataExplorerViewFactory.class, immediate = false)
30 | public class GoogleDicomExplorerFactory implements DataExplorerViewFactory {
31 |
32 | private GoogleDicomExplorer explorer = null;
33 | private final Logger LOGGER = LoggerFactory.getLogger(GoogleDicomExplorerFactory.class);
34 |
35 | @Override
36 | public DataExplorerView createDataExplorerView(Hashtable properties) {
37 | if (explorer == null) {
38 | explorer = new GoogleDicomExplorer();
39 | ViewerPluginBuilder.DefaultDataModel.firePropertyChange(
40 | new ObservableEvent(ObservableEvent.BasicAction.NULL_SELECTION, explorer, null, null));
41 | }
42 | return explorer;
43 | }
44 |
45 | // ================================================================================
46 | // OSGI service implementation
47 | // ================================================================================
48 |
49 | @Activate
50 | protected void activate(ComponentContext context) {
51 |
52 | LOGGER.info("Activate the Google Healthcare DataExplorerView");
53 | }
54 |
55 | @Deactivate
56 | protected void deactivate(ComponentContext context) {
57 | LOGGER.info("Deactivate the Google Healthcare DataExplorerView");
58 | }
59 | }
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/AutoRefreshComboBoxExtension.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import javax.swing.JComboBox;
18 | import javax.swing.event.ListDataEvent;
19 | import javax.swing.event.ListDataListener;
20 | import java.awt.event.MouseAdapter;
21 | import java.awt.event.MouseEvent;
22 | import java.util.function.Supplier;
23 |
24 | public class AutoRefreshComboBoxExtension {
25 |
26 | private static final long TIME_TO_INVALIDATE_CACHE_MS = 10_000;
27 |
28 | private long lastUpdateTime = System.currentTimeMillis();
29 |
30 | private AutoRefreshComboBoxExtension(JComboBox> comboBox, Supplier reload) {
31 | addDataUpdateListener(comboBox);
32 | addDataReloadListener(comboBox, reload);
33 | }
34 |
35 | public static AutoRefreshComboBoxExtension wrap(JComboBox> comboBox, Supplier reload) {
36 | return new AutoRefreshComboBoxExtension(comboBox, reload);
37 | }
38 |
39 | private void addDataReloadListener(JComboBox> comboBox, Supplier reload) {
40 | comboBox.addMouseListener(new MouseAdapter() {
41 | @Override
42 | public void mousePressed(MouseEvent e) {
43 | if (isTimeoutPassed()) {
44 | if (Boolean.TRUE.equals(reload.get())) {
45 | lastUpdateTime = System.currentTimeMillis();
46 | }
47 | }
48 | }
49 | });
50 | }
51 |
52 | private void addDataUpdateListener(JComboBox> comboBox) {
53 | comboBox.getModel().addListDataListener(new ListDataListener() {
54 | @Override
55 | public void intervalAdded(ListDataEvent e) {
56 | lastUpdateTime = System.currentTimeMillis();
57 | }
58 |
59 | @Override
60 | public void intervalRemoved(ListDataEvent e) {
61 | lastUpdateTime = System.currentTimeMillis();
62 | }
63 |
64 | @Override
65 | public void contentsChanged(ListDataEvent e) {
66 | lastUpdateTime = System.currentTimeMillis();
67 | }
68 | });
69 | }
70 |
71 | private boolean isTimeoutPassed() {
72 | return (System.currentTimeMillis() - lastUpdateTime) > TIME_TO_INVALIDATE_CACHE_MS;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/GoogleLoginTask.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package org.weasis.dicom.google.api.ui.dicomstore;
15 |
16 | import javax.swing.JButton;
17 | import javax.swing.JOptionPane;
18 | import javax.swing.SwingWorker;
19 |
20 | import org.weasis.core.api.gui.util.GuiExecutor;
21 | import org.weasis.dicom.google.api.GoogleAPIClient;
22 | import org.weasis.dicom.google.explorer.Messages;
23 |
24 | public class GoogleLoginTask extends SwingWorker {
25 | protected final GoogleAPIClient googleAPIClient;
26 | protected final JButton googleAuthButton;
27 | protected final DicomStoreSelector view;
28 |
29 | private static final String TEXT_GOOGLE_SIGN_IN = Messages.getString("DicomStoreSelector.sign_in"); //$NON-NLS-1$
30 | private static final String TEXT_GOOGLE_SIGN_OUT = Messages.getString("DicomStoreSelector.sign_out"); //$NON-NLS-1$
31 | private static final String ACTION_SIGN_OUT = Messages.getString("DicomStoreSelector.sign_out");
32 | private static final String ACTION_SIGN_IN = Messages.getString("DicomStoreSelector.sign_in");
33 |
34 | public GoogleLoginTask(GoogleAPIClient apiClient, JButton googleAuthButton, DicomStoreSelector view) {
35 | this.googleAPIClient = apiClient;
36 | this.googleAuthButton = googleAuthButton;
37 | this.view = view;
38 | }
39 |
40 |
41 | @Override
42 | protected Void doInBackground() {
43 | try {
44 | googleAPIClient.signIn();
45 | googleAuthButton.setText(TEXT_GOOGLE_SIGN_OUT);
46 | googleAuthButton.setActionCommand(ACTION_SIGN_OUT);
47 | new LoadProjectsTask(googleAPIClient, view).execute();
48 | } catch (Exception ex) {
49 | GuiExecutor.instance().invokeAndWait(() -> JOptionPane.showMessageDialog(null,
50 | "Error occured on fetching google API.\n" +
51 | "Make sure you created OAuth Client ID credential \n" +
52 | "in Google Cloud console at https://console.cloud.google.com/apis/credentials \n" +
53 | "and copied your client_secrets.json to Weasis root folder.\n" +
54 | "Error message:" + ex.getCause().getMessage()));
55 |
56 | googleAPIClient.signOut();
57 | googleAuthButton.setText(TEXT_GOOGLE_SIGN_IN);
58 | googleAuthButton.setActionCommand(ACTION_SIGN_IN);
59 | }
60 | return null;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/GoogleExplorer.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui;
16 |
17 | import org.weasis.dicom.google.api.GoogleAPIClient;
18 | import org.weasis.dicom.google.api.ui.dicomstore.DicomStoreSelector;
19 | import org.weasis.dicom.google.explorer.DownloadManager;
20 |
21 | import javax.swing.JPanel;
22 | import javax.swing.BoxLayout;
23 | import javax.swing.Box;
24 |
25 | import java.awt.BorderLayout;
26 | import java.awt.Component;
27 |
28 | import static javax.swing.BoxLayout.PAGE_AXIS;
29 |
30 | public class GoogleExplorer extends JPanel {
31 |
32 | private final StudiesTable table;
33 | private final GoogleAPIClient googleAPIClient;
34 | private final DicomStoreSelector storeSelector;
35 |
36 | private final SearchPanel searchPanel;
37 | private final NavigationPanel navigationPanel;
38 |
39 | public GoogleExplorer(GoogleAPIClient googleAPIClient) {
40 | this.googleAPIClient = googleAPIClient;
41 |
42 | BorderLayout layout = new BorderLayout();
43 |
44 | layout.setHgap(15);
45 | setLayout(layout);
46 |
47 | table = new StudiesTable(this);
48 | storeSelector = new DicomStoreSelector(googleAPIClient, table);
49 | searchPanel = new SearchPanel(storeSelector);
50 | navigationPanel = new NavigationPanel(searchPanel);
51 | add(centralComponent(), BorderLayout.CENTER);
52 | add(searchPanel, BorderLayout.WEST);
53 | }
54 |
55 | public Component centralComponent() {
56 | JPanel panel = new JPanel();
57 | BoxLayout layout = new BoxLayout(panel, PAGE_AXIS);
58 | panel.setLayout(layout);
59 |
60 | panel.add(storeSelector);
61 | panel.add(Box.createVerticalStrut(10));
62 | panel.add(table);
63 | panel.add(navigationPanel);
64 | return panel;
65 | }
66 |
67 | public void fireStudySelected(String studyId) {
68 | storeSelector.getCurrentStore()
69 | .map(store -> GoogleAPIClient.getImageUrl(store, studyId))
70 | .ifPresent(image -> {
71 | DownloadManager.getLoadingExecutor().submit(
72 | new DownloadManager.LoadGoogleDicom(image, null, googleAPIClient, new DownloadManager.DownloadListener() {
73 | @Override
74 | public void downloadFinished() {
75 | table.hideLoadIcon(studyId);
76 | }
77 | }));
78 | table.showLoadIcon(studyId);
79 | });
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/model/StudyQuery.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.model;
16 |
17 | import java.time.LocalDate;
18 |
19 | public class StudyQuery {
20 |
21 | private LocalDate startDate;
22 | private LocalDate endDate;
23 | private String patientName;
24 | private String patientId;
25 |
26 | private String accessionNumber;
27 | private String physicianName;
28 | private int page;
29 | private int pageSize;
30 | private boolean fuzzyMatching;
31 |
32 | public String getPatientName() {
33 | return patientName;
34 | }
35 |
36 | public void setPatientName(String patientName) {
37 | this.patientName = patientName;
38 | }
39 |
40 | public String getPatientId() {
41 | return patientId;
42 | }
43 |
44 | public void setPatientId(String patientId) {
45 | this.patientId = patientId;
46 | }
47 |
48 | public LocalDate getStartDate() {
49 | return startDate;
50 | }
51 |
52 | public void setStartDate(LocalDate startDate) {
53 | this.startDate = startDate;
54 | }
55 |
56 | public LocalDate getEndDate() {
57 | return endDate;
58 | }
59 |
60 | public void setEndDate(LocalDate endDate) {
61 | this.endDate = endDate;
62 | }
63 |
64 | public String getAccessionNumber() {
65 | return accessionNumber;
66 | }
67 |
68 | public void setAccessionNumber(String accessionNumber) {
69 | this.accessionNumber = accessionNumber;
70 | }
71 |
72 | public String getPhysicianName() {
73 | return physicianName;
74 | }
75 |
76 | public void setPhysicianName(String physicianName) {
77 | this.physicianName = physicianName;
78 | }
79 |
80 | public void setPage(int offset) {
81 | this.page = offset;
82 | }
83 |
84 | public int getPage() {
85 | return this.page;
86 | }
87 |
88 | public int getPageSize() {
89 | return this.pageSize;
90 | }
91 |
92 | /** Set how many objects will be requested for each page
93 | * Please note it may be hard for UI to display too many objects
94 | */
95 | public void setPageSize(int pageSize) {
96 | this.pageSize = pageSize;
97 | }
98 |
99 | public void setFuzzyMatching(boolean fuzzyMatching) {
100 | this.fuzzyMatching = fuzzyMatching;
101 | }
102 |
103 | public boolean getFuzzyMatching() {
104 | return fuzzyMatching;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!IMPORTANT]
2 | > Weasis now supports DICOMweb. This makes this extension obsolete. This repository has been archived and will not receive further updates. For details on how to integrate Weasis with DICOMweb end-points from Google Cloud Healthcare, please check https://weasis.org/en/tutorials/dicomweb-config/#google-cloud-healthcare-api
3 |
4 | ## About Weasis Google DICOM Plugin
5 |
6 | Plugin enables Weasis Viewer users access to [Google Cloud Healthcare API](https://cloud.google.com/healthcare) DICOM data.
7 | It utilizes [DICOMweb REST API](https://cloud.google.com/healthcare/docs/how-tos/dicomweb) to interact with Google Cloud services.
8 |
9 | ### Features
10 |
11 | * Login using your Google account
12 | * Interactive exploration of Google Healthcare API Dicom stores
13 | * Download and display all kinds of DICOM data
14 | * Advanced study search capabilities
15 |
16 | 
17 |
18 | ### Running the plugin
19 |
20 | The plugin runs as an extension to the main Weasis application, so first you
21 | need to download the main Weasis application from https://nroduit.github.io/en/.
22 |
23 | ***Please note, latest supported release of Weasis is [3.6.0](https://github.com/nroduit/Weasis/releases/tag/v3.6.0)***
24 |
25 | Then you need to have existing data in the Cloud Healthcare API and install the
26 | plugin to get up and running. Please see more detailed instructions below.
27 |
28 | #### Setting up Google Cloud Healthcare API:
29 |
30 | See https://cloud.google.com/healthcare/docs/ to get started.
31 |
32 | #### Installing plugin
33 |
34 | * Get the latest release JAR from this repositories releases tab.
35 | * Follow instructions at [installing
36 | plug-ins](https://nroduit.github.io/en/basics/customize/build-plugins/#install-plug-ins)
37 | to add this plugin to Weasis.
38 | * Run Weasis Viewer executable
39 | * Switch to **_Google Dicom Explorer_** tab and login using your Google Account
40 | > NOTE: If you face with some issues when using the plugin, you should remove .Weasis folder wich may cache previous or
41 | > incorrect settings for the plugin in Weasis.
42 |
43 | #### Using your own OAuth client
44 |
45 | The plugin comes with it's own OAuth Client ID for ease of installation, but you can substitute
46 | your own if required (e.g. your organization has OAuth policy restriction on external apps). To do
47 | this go to the [Google API Console](https://console.developers.google.com/) and create a set of
48 | OAuth 2.0 credentials using the type "Other" and make sure to whitelist the scopes
49 | `.../auth/cloud-healthcare` and `.../auth/cloudplatformprojects.readonly`. Then download the
50 | credentials files in JSON format, name the file `client_secrets.json` and move it to conf
51 | folder, next to the ext-config.properties file.
52 |
53 | ### Building plugin
54 |
55 | If you're just trying to run the tool, please see the instructions above. If you
56 | need to recompile the plugin for any reason here are the steps to do so.
57 |
58 | Weasis requires JDK14.
59 | Plugin depends on core Weasis API, that's why you have to clone, build and install core Weasis modules to
60 | your local Maven repository first
61 | For this purpose follow instructions at [building Weasis](https://nroduit.github.io/en/getting-started/building-weasis/).
62 | After Weasis artifacts installed to your local Maven repository plugin itself can be compiled
63 | Detailed build instruction can be found at
64 | [building Weasis plugins](https://nroduit.github.io/en/basics/customize/build-plugins/)
65 | Clone this repository and execute following script:
66 | ```bash
67 | cd weasis-chcapi-extension
68 |
69 | ## build plugin
70 | mvn clean install
71 | ```
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/StudyView.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui;
16 |
17 | import java.time.LocalDate;
18 | import java.time.LocalTime;
19 |
20 | public class StudyView {
21 |
22 | private String studyId;
23 | private String patientName;
24 | private String patientId;
25 | private String accountNumber;
26 | private String noi;
27 | private LocalDate studyDate;
28 | private LocalTime studyTime;
29 | private String type;
30 | private String description;
31 | private String refPhd;
32 | private String reqPhd;
33 | private String location;
34 | private LocalDate birthDate;
35 |
36 | public String getStudyId() {
37 | return studyId;
38 | }
39 |
40 | public void setStudyId(String studyId) {
41 | this.studyId = studyId;
42 | }
43 |
44 | public String getPatientName() {
45 | return patientName;
46 | }
47 |
48 | public void setPatientName(String patientName) {
49 | this.patientName = patientName;
50 | }
51 |
52 | public String getPatientId() {
53 | return patientId;
54 | }
55 |
56 | public void setPatientId(String patientId) {
57 | this.patientId = patientId;
58 | }
59 |
60 | public String getAccountNumber() {
61 | return accountNumber;
62 | }
63 |
64 | public void setAccountNumber(String accountNumber) {
65 | this.accountNumber = accountNumber;
66 | }
67 |
68 | public String getNoi() {
69 | return noi;
70 | }
71 |
72 | public void setNoi(String noi) {
73 | this.noi = noi;
74 | }
75 |
76 | public LocalDate getStudyDate() {
77 | return studyDate;
78 | }
79 |
80 | public void setStudyDate(LocalDate studyDate) {
81 | this.studyDate = studyDate;
82 | }
83 |
84 | public LocalTime getStudyTime() {
85 | return studyTime;
86 | }
87 |
88 | public void setStudyTime(LocalTime studyTime) {
89 | this.studyTime = studyTime;
90 | }
91 |
92 | public String getType() {
93 | return type;
94 | }
95 |
96 | public void setType(String type) {
97 | this.type = type;
98 | }
99 |
100 | public String getDescription() {
101 | return description;
102 | }
103 |
104 | public void setDescription(String description) {
105 | this.description = description;
106 | }
107 |
108 | public String getRefPhd() {
109 | return refPhd;
110 | }
111 |
112 | public void setRefPhd(String refPhd) {
113 | this.refPhd = refPhd;
114 | }
115 |
116 | public String getReqPhd() {
117 | return reqPhd;
118 | }
119 |
120 | public void setReqPhd(String reqPhd) {
121 | this.reqPhd = reqPhd;
122 | }
123 |
124 | public String getLocation() {
125 | return location;
126 | }
127 |
128 | public void setLocation(String location) {
129 | this.location = location;
130 | }
131 |
132 | public LocalDate getBirthDate() {
133 | return birthDate;
134 | }
135 |
136 | public void setBirthDate(LocalDate birthDate) {
137 | this.birthDate = birthDate;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/explorer/GoogleDicomExplorer.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.explorer;
16 |
17 | import bibliothek.gui.dock.common.CLocation;
18 | import bibliothek.gui.dock.common.mode.ExtendedMode;
19 | import org.weasis.core.api.explorer.DataExplorerView;
20 | import org.weasis.core.api.explorer.model.DataExplorerModel;
21 | import org.weasis.core.ui.docking.PluginTool;
22 | import org.weasis.core.ui.editor.SeriesViewerEvent;
23 | import org.weasis.core.ui.editor.SeriesViewerListener;
24 | import org.weasis.dicom.google.api.GoogleAPIClient;
25 | import org.weasis.dicom.google.api.GoogleAPIClientFactory;
26 | import org.weasis.dicom.google.api.ui.GoogleExplorer;
27 |
28 | import javax.swing.*;
29 | import java.awt.*;
30 | import java.beans.PropertyChangeEvent;
31 | import java.io.File;
32 | import java.util.List;
33 |
34 | public class GoogleDicomExplorer extends PluginTool implements DataExplorerView, SeriesViewerListener {
35 |
36 | public static final String NAME = Messages.getString("GoogleDicomExplorer.title"); //$NON-NLS-1$
37 | public static final String BUTTON_NAME = Messages.getString("GoogleDicomExplorer.btn_title"); //$NON-NLS-1$
38 | public static final String DESCRIPTION = Messages.getString("GoogleDicomExplorer.desc"); //$NON-NLS-1$
39 |
40 | private final GoogleExplorer explorer;
41 |
42 | private final GoogleAPIClient googleAPIClient = GoogleAPIClientFactory.getInstance().createGoogleClient();
43 |
44 | public GoogleDicomExplorer() {
45 | super(NAME, BUTTON_NAME, POSITION.WEST, null,//ExtendedMode.NORMALIZED,
46 | PluginTool.Type.EXPLORER, 120);
47 | setLayout(new BorderLayout());
48 |
49 | explorer = new GoogleExplorer(googleAPIClient);
50 | add(explorer);
51 | setDockableWidth(500);
52 | dockable.setMaximizable(true);
53 | dockable.setMinimizable(true);
54 | }
55 |
56 |
57 | @Override
58 | public void dispose() {
59 | super.closeDockable();
60 | }
61 |
62 | @Override
63 | public DataExplorerModel getDataExplorerModel() {
64 | return null;
65 | }
66 |
67 | @Override
68 | public List getOpenImportDialogAction() {
69 | return null;
70 | }
71 |
72 | @Override
73 | public List getOpenExportDialogAction() {
74 | return null;
75 | }
76 |
77 | @Override
78 | public void importFiles(File[] files, boolean recursive) {
79 | }
80 |
81 | @Override
82 | public boolean canImportFiles() {
83 | return false;
84 | }
85 |
86 | @Override
87 | public void propertyChange(PropertyChangeEvent evt) {
88 | }
89 |
90 | @Override
91 | public String getUIName() {
92 | return NAME;
93 | }
94 |
95 | @Override
96 | public String toString() {
97 | return NAME;
98 | }
99 |
100 | @Override
101 | public String getDescription() {
102 | return DESCRIPTION;
103 | }
104 |
105 | @Override
106 | protected void changeToolWindowAnchor(CLocation clocation) {
107 | }
108 |
109 | @Override
110 | public void changingViewContentEvent(SeriesViewerEvent event) {
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/OAuth2Browser.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui;
16 |
17 | import java.util.logging.Level;
18 | import java.util.logging.Logger;
19 |
20 | import java.io.IOException;
21 |
22 | import java.net.URI;
23 |
24 | import java.awt.Toolkit;
25 | import java.awt.Desktop;
26 | import java.awt.Desktop.Action;
27 | import java.awt.datatransfer.StringSelection;
28 |
29 | import javax.swing.JOptionPane;
30 | import javax.swing.SwingUtilities;
31 | import org.weasis.dicom.google.explorer.Messages;
32 |
33 | import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
34 | import com.google.api.client.util.Preconditions;
35 |
36 | /**
37 | * OAuth2 authorization browser that copies the authorization URL to the clipboard and shows the
38 | * notification dialog if there is no default browser configured or an error occurred while opening
39 | * the default browser.
40 | *
41 | * @author Mikhail Ukhlin
42 | * @see AuthorizationCodeInstalledApp
43 | */
44 | public class OAuth2Browser implements AuthorizationCodeInstalledApp.Browser {
45 |
46 | private static final Logger LOGGER =
47 | Logger.getLogger(OAuth2Browser.class.getName());
48 |
49 | /**
50 | * Single instance of this browser.
51 | */
52 | public static final AuthorizationCodeInstalledApp.Browser INSTANCE = new OAuth2Browser();
53 |
54 | /**
55 | * Do not allow more than one instance.
56 | */
57 | private OAuth2Browser() {
58 | super();
59 | }
60 |
61 | /**
62 | * Opens a browser at the given URL using {@link Desktop} if available, or alternatively copies
63 | * authorization URL to clipboard and shows notification dialog.
64 | *
65 | * @param url URL to browse.
66 | * @throws IOException if an IO error occurred.
67 | * @see AuthorizationCodeInstalledApp#browse(String)
68 | */
69 | @Override
70 | public void browse(String url) throws IOException {
71 | Preconditions.checkNotNull(url);
72 | // Ask user to open in their browser using copy-paste
73 | System.out.println("Please open the following address in your browser:");
74 | System.out.println(" " + url);
75 | // Attempt to open it in the browser
76 | try {
77 | if (Desktop.isDesktopSupported()) {
78 | Desktop desktop = Desktop.getDesktop();
79 | if (desktop.isSupported(Action.BROWSE)) {
80 | System.out.println("Attempting to open that address in the default browser now...");
81 | desktop.browse(URI.create(url));
82 | } else {
83 | showNotification(url);
84 | }
85 | } else {
86 | showNotification(url);
87 | }
88 | } catch (IOException e) {
89 | LOGGER.log(Level.WARNING, "Unable to open browser", e);
90 | showNotification(url);
91 | } catch (InternalError e) {
92 | // A bug in a JRE can cause Desktop.isDesktopSupported() to throw an
93 | // InternalError rather than returning false. The error reads,
94 | // "Can't connect to X11 window server using ':0.0' as the value of the
95 | // DISPLAY variable." The exact error message may vary slightly.
96 | LOGGER.log(Level.WARNING, "Unable to open browser", e);
97 | showNotification(url);
98 | }
99 | }
100 |
101 | /**
102 | * Copies authorization URL to clipboard and shows notification dialog.
103 | *
104 | * @param url URL to browse.
105 | */
106 | private static void showNotification(String url) {
107 | // Copy authorization URL to clipboard
108 | final StringSelection selection = new StringSelection(url);
109 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
110 | // Show notification dialog
111 | SwingUtilities.invokeLater(() -> {
112 | JOptionPane.showMessageDialog(null,
113 | Messages.getString("GoogleAPIClient.open_browser_message"));
114 | });
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/dicomstore/LoadStudiesTask.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui.dicomstore;
16 |
17 | import org.weasis.dicom.google.api.GoogleAPIClient;
18 | import org.weasis.dicom.google.api.model.DicomStore;
19 | import org.weasis.dicom.google.api.model.StudyModel;
20 | import org.weasis.dicom.google.api.model.StudyQuery;
21 | import org.weasis.dicom.google.api.ui.StudyView;
22 |
23 | import java.time.LocalDate;
24 | import java.time.LocalTime;
25 | import java.time.format.DateTimeFormatter;
26 | import java.time.format.DateTimeFormatterBuilder;
27 | import java.time.temporal.ChronoField;
28 | import java.util.List;
29 |
30 | import static java.util.stream.Collectors.toList;
31 |
32 | public class LoadStudiesTask extends AbstractDicomSelectorTask> {
33 |
34 | private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
35 | private static final DateTimeFormatter TIME_FORMAT = new DateTimeFormatterBuilder()
36 | .appendPattern("HH[:]mm[:]ss")
37 | .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
38 | .toFormatter();
39 |
40 | private final DicomStore store;
41 | private final StudyQuery query;
42 |
43 |
44 | public LoadStudiesTask(DicomStore store,
45 | GoogleAPIClient api,
46 | DicomStoreSelector view,
47 | StudyQuery studyQuery) {
48 | super(api, view);
49 | this.store = store;
50 | this.query = studyQuery;
51 | }
52 |
53 | @Override
54 | protected List doInBackground() throws Exception {
55 | List studies = api.fetchStudies(store, query);
56 |
57 | return studies.stream().map(this::parse).collect(toList());
58 | }
59 |
60 | private StudyView parse(StudyModel model) {
61 | StudyView view = new StudyView();
62 |
63 | if (model.getStudyInstanceUID() != null) {
64 | view.setStudyId(model.getStudyInstanceUID().getFirstValue().orElse(""));
65 | }
66 | if (model.getPatientName() != null) {
67 | view.setPatientName(model.getPatientName().getFirstValue().map(StudyModel.Value::getAlphabetic).orElse(""));
68 | }
69 | if (model.getPatientId() != null) {
70 | view.setPatientId(model.getPatientId().getFirstValue().orElse(""));
71 | }
72 | if (model.getAccessionNumber() != null) {
73 | view.setAccountNumber(model.getAccessionNumber().getFirstValue().orElse(""));
74 | }
75 | if (model.getStudyDate() != null) {
76 | try {
77 | view.setStudyDate(model.getStudyDate().getFirstValue().map(s -> LocalDate.parse(s, DATE_FORMAT)).orElse(null));
78 | } catch (Exception e) {
79 | try {
80 | view.setStudyDate(model.getStudyDate().getFirstValue().map(s -> LocalDate.parse(s, DateTimeFormatter.ofPattern("yyyy.MM.dd"))).orElse(null));
81 | } catch (Exception ignored) {
82 | }
83 | }
84 | }
85 | if (model.getStudyTime() != null) {
86 | try {
87 | view.setStudyTime(model.getStudyTime().getFirstValue().map(s -> LocalTime.parse(s, TIME_FORMAT)).orElse(null));
88 | } catch (Exception ignored) {
89 | }
90 | }
91 | if (model.getStudyDescription() != null) {
92 | view.setDescription(model.getStudyDescription().getFirstValue().orElse(""));
93 | }
94 | if (model.getRefPhd() != null) {
95 | view.setRefPhd(model.getRefPhd().getFirstValue().map(StudyModel.Value::getAlphabetic).orElse(""));
96 | }
97 | if (model.getReqPhd() != null) {
98 | view.setReqPhd(model.getReqPhd().getFirstValue().map(StudyModel.Value::getAlphabetic).orElse(""));
99 | }
100 | if (model.getLocation() != null) {
101 | view.setLocation(model.getLocation().getFirstValue().map(StudyModel.Value::getAlphabetic).orElse(""));
102 | }
103 | if (model.getBirthDate() != null) {
104 | try {
105 | view.setBirthDate(model.getBirthDate().getFirstValue().map(s -> LocalDate.parse(s, DATE_FORMAT)).orElse(null));
106 | } catch (Exception ignored) {
107 | }
108 | }
109 |
110 | return view;
111 | }
112 |
113 | @Override
114 | protected void onCompleted(List result) {
115 | view.updateTable(result);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/weasis/dicom/google/api/ui/StudiesTable.java:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.weasis.dicom.google.api.ui;
16 |
17 | import org.slf4j.Logger;
18 | import org.slf4j.LoggerFactory;
19 |
20 | import javax.swing.JPanel;
21 | import javax.swing.JTable;
22 | import javax.swing.JScrollPane;
23 | import javax.swing.ImageIcon;
24 | import javax.swing.table.DefaultTableModel;
25 | import javax.swing.table.TableModel;
26 |
27 | import java.awt.BorderLayout;
28 | import java.awt.Font;
29 | import java.awt.Image;
30 | import java.awt.Point;
31 | import java.awt.event.MouseAdapter;
32 | import java.awt.event.MouseEvent;
33 | import java.awt.image.ImageObserver;
34 | import java.util.ArrayList;
35 | import java.util.List;
36 | import java.util.Objects;
37 | import java.util.Vector;
38 |
39 | public class StudiesTable extends JPanel {
40 |
41 | private static final Logger LOGGER = LoggerFactory.getLogger(StudiesTable.class);
42 |
43 | private ImageIcon loadIcon = new ImageIcon(this.getClass().getResource("/loading.gif"));
44 |
45 | private static final Object[] COLUMN_NAMES = {
46 | "Status","Patient name", "Patient ID", "ACC.#", "Study date", "Study time",
47 | "Desc", "REF.PHD", "REQ.PHD", "LOCATION", "BIRTH DATE"
48 | };
49 |
50 | private final DefaultTableModel tableModel;
51 |
52 | private final List studies = new ArrayList<>();
53 | private final GoogleExplorer explorer;
54 | private final JTable table;
55 |
56 | public StudiesTable(GoogleExplorer explorer) {
57 | this.explorer = explorer;
58 | tableModel = new DefaultTableModel(COLUMN_NAMES, 0) {
59 | @Override
60 | public boolean isCellEditable(int row, int column) {
61 | return false;
62 | }
63 | @Override
64 | public Class> getColumnClass(int columnIndex) {
65 | if (columnIndex == 0) {
66 | return ImageIcon.class;
67 | }
68 | return super.getColumnClass(columnIndex);
69 | }
70 | };
71 |
72 | table = new JTable(tableModel);
73 | table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
74 | JScrollPane scrollPane = new JScrollPane(table);
75 | table.setFillsViewportHeight(true);
76 | table.setFont(new Font("Sans-serif", Font.PLAIN, 14));
77 |
78 | BorderLayout layout = new BorderLayout();
79 | setLayout(layout);
80 | add(scrollPane, BorderLayout.CENTER);
81 |
82 | table.addMouseListener(new MouseAdapter() {
83 | public void mousePressed(MouseEvent mouseEvent) {
84 | JTable table = (JTable) mouseEvent.getSource();
85 | Point point = mouseEvent.getPoint();
86 | int row = table.rowAtPoint(point);
87 | if (mouseEvent.getClickCount() == 2
88 | && row >= 0) {
89 | StudyView study = studies.get(row);
90 | explorer.fireStudySelected(study.getStudyId());
91 | }
92 | }
93 | });
94 | }
95 |
96 | private void setImageObserver(JTable table) {
97 | TableModel model = table.getModel();
98 | int rowCount = model.getRowCount();
99 | int col = 0;
100 | if (ImageIcon.class == model.getColumnClass(col)) {
101 | for (int row = 0; row < rowCount; row++) {
102 | Object obj = model.getValueAt(row, col);
103 | ImageIcon icon = null;
104 | if (obj instanceof ImageIcon) {
105 | icon = (ImageIcon) model.getValueAt(row, col);
106 | }
107 | if (icon != null && icon.getImageObserver() == null) {
108 | icon.setImageObserver(new CellImageObserver(table, row, col));
109 | }
110 | }
111 | }
112 | }
113 |
114 | class CellImageObserver implements ImageObserver {
115 | JTable table;
116 | int row;
117 | int col;
118 |
119 | CellImageObserver(JTable table, int row, int col) {
120 | this.table = table;
121 | this.row = row;
122 | this.col = col;
123 | }
124 |
125 | public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) {
126 | if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
127 | table.repaint();
128 | }
129 | return (flags & (ALLBITS | ABORT)) == 0;
130 | }
131 | }
132 |
133 | public void showLoadIcon(String studyId) {
134 | for (int i=0;i < studies.size();i++) {
135 | if (Objects.equals(studies.get(i).getStudyId(), studyId)) {
136 | table.setValueAt(loadIcon, i, 0);
137 | break;
138 | }
139 | }
140 | setImageObserver(table);
141 | }
142 |
143 | public void hideLoadIcon(String studyId) {
144 | for (int i=0;i < studies.size();i++) {
145 | if (Objects.equals(studies.get(i).getStudyId(), studyId)) {
146 | table.setValueAt(null, i, 0);
147 | break;
148 | }
149 | }
150 | setImageObserver(table);
151 | }
152 |
153 | public void addStudy(StudyView study) {
154 | LOGGER.info("Adding record");
155 | Vector