blob: d9b5cec346eb9ca4f12cbceac6baf80fa96da3c9 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.services.creators;
import com.android.tools.idea.structure.services.DeveloperServiceCreator;
import com.android.tools.idea.structure.services.ServiceContext;
import com.android.tools.idea.ui.properties.BindingsManager;
import com.android.tools.idea.ui.properties.InvalidationListener;
import com.android.tools.idea.ui.properties.Observable;
import com.android.tools.idea.ui.properties.collections.ObservableList;
import com.android.tools.idea.ui.properties.core.BoolValueProperty;
import com.android.tools.idea.ui.properties.core.IntValueProperty;
import com.android.tools.idea.ui.properties.core.ObservableBool;
import com.android.tools.idea.ui.properties.core.StringValueProperty;
import com.android.tools.idea.ui.properties.expressions.bool.BooleanExpression;
import com.android.tools.idea.ui.properties.expressions.bool.BooleanExpressions;
import com.android.tools.idea.ui.properties.expressions.list.AbstractMapExpression;
import com.android.tools.idea.ui.properties.expressions.list.SizeExpression;
import com.android.tools.idea.ui.properties.expressions.string.IsEmptyExpression;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.analytics.Analytics;
import com.google.api.services.analytics.model.Account;
import com.google.api.services.analytics.model.Accounts;
import com.google.api.services.analytics.model.Webproperties;
import com.google.api.services.analytics.model.Webproperty;
import com.google.gct.login.CredentialedUser;
import com.google.gct.login.GoogleLogin;
import com.google.services.GoogleServiceCreators;
import com.google.services.GoogleServiceLoginListener;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Callable;
public final class AnalyticsServiceCreator extends DeveloperServiceCreator {
private final ObservableBool myLoggedIn = GoogleServiceLoginListener.getInstance().loggedIn();
private final ObservableList<Account> myAccounts = new ObservableList<Account>();
private final ObservableList<Webproperty> myProperties = new ObservableList<Webproperty>();
private final IntValueProperty myAccountIndex = new IntValueProperty(-1);
private final IntValueProperty myPropertyIndex = new IntValueProperty(-1);
private final StringValueProperty myPropertyId = new StringValueProperty();
private final BoolValueProperty myAdsEnabled = new BoolValueProperty();
private final ObservableList<String> myAccountNames = new ObservableList<String>();
private final ObservableList<String> myPropertyNames = new ObservableList<String>();
@SuppressWarnings("FieldCanBeLocal") // Declared as field to prevent garbage collection
private final BindingsManager myBindings = new BindingsManager();
@SuppressWarnings("FieldCanBeLocal") // Declared as field to prevent weak reference collection
private final InvalidationListener myLoginListener = new InvalidationListener() {
@Override
protected void onInvalidated(@NotNull Observable sender) {
if (myLoggedIn.get()) {
refreshProjects();
}
else {
myAccounts.clear();
myProperties.clear();
myAccountIndex.set(-1);
myPropertyIndex.set(-1);
}
}
};
public AnalyticsServiceCreator() {
myLoggedIn.addWeakListener(myLoginListener);
// Map accounts to account names
myBindings.bindList(myAccountNames, new AbstractMapExpression<Account, String>(myAccounts) {
@NotNull
@Override
protected String transform(@NotNull Account account) {
return account.getName();
}
});
// Map properties to property names
myBindings.bindList(myPropertyNames, new AbstractMapExpression<Webproperty, String>(myProperties) {
@NotNull
@Override
protected String transform(@NotNull Webproperty property) {
return property.getName();
}
});
myAccountIndex.addListener(new InvalidationListener() {
@Override
protected void onInvalidated(@NotNull Observable sender) {
if (myAccountIndex.get() >= 0) {
refreshProperties();
}
}
});
myPropertyIndex.addListener(new InvalidationListener() {
@Override
protected void onInvalidated(@NotNull Observable sender) {
if (myPropertyIndex.get() >= 0) {
//noinspection ConstantConditions
myPropertyId.set(myProperties.get(myPropertyIndex.get()).getId());
}
}
});
}
@NotNull
@Override
protected String getResourceRoot() {
return "/analytics";
}
@NotNull
@Override
protected String[] getResources() {
return new String[]{"AnalyticsTrackers.java.ftl", "AndroidManifest.xml", "app_tracker.xml.ftl", "logo_analytics_color_2x_web_32dp.png",
"recipe.xml", "service.xml"};
}
@Override
protected void initializeContext(@NotNull ServiceContext serviceContext) {
GoogleServiceCreators.initializeGoogleContext(serviceContext);
serviceContext.putValue("google.analytics.accounts", myAccountNames);
serviceContext.putValue("google.analytics.accountIndex", myAccountIndex);
serviceContext.putValue("google.analytics.properties", myPropertyNames);
serviceContext.putValue("google.analytics.propertyIndex", myPropertyIndex);
serviceContext.putValue("google.analytics.hasNoAccount", new SizeExpression(myAccounts).isEqualTo(0).and(myLoggedIn));
serviceContext.putValue("google.analytics.hasAccount", new SizeExpression(myAccounts).isGreaterThan(0));
serviceContext.putAction("google.analytics.refreshProjects", new Runnable() {
@Override
public void run() {
refreshProjects();
}
});
serviceContext.putAction("google.analytics.createProject", new Runnable() {
@Override
public void run() {
browse("https://support.google.com/analytics/answer/1008015");
}
});
serviceContext.putWatchedValue("google.analytics.propertyId", myPropertyId);
serviceContext.putWatchedValue("google.analytics.adsEnabled", myAdsEnabled);
serviceContext.setBeforeShownCallback(new Runnable() {
@Override
public void run() {
if (myLoggedIn.get()) {
refreshProjects();
}
}
});
serviceContext.setIsValidCallback(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return !myPropertyId.get().isEmpty();
}
});
}
private void refreshProjects() {
final CredentialedUser user = GoogleLogin.getInstance().getActiveUser();
assert user != null;
Callable<Accounts> fetchAccounts = new Callable<Accounts>() {
@Override
public Accounts call() throws Exception {
Analytics analytics =
new Analytics.Builder(new NetHttpTransport(), new JacksonFactory(), user.getCredential()).setApplicationName("Android Studio")
.build();
Accounts accounts = analytics.management().accounts().list().execute();
if (accounts != null && accounts.getItems().size() > 0) {
return accounts;
}
return null;
}
};
Dispatchable<Accounts> onAccountsFetched = new Dispatchable<Accounts>() {
@Override
public void dispatch(@NotNull Accounts accounts) {
myAccounts.setAll(accounts.getItems());
myAccountIndex.set(0);
}
};
runInBackground(fetchAccounts, onAccountsFetched);
}
private void refreshProperties() {
final Account account = myAccounts.get(myAccountIndex.get());
assert account != null;
final CredentialedUser user = GoogleLogin.getInstance().getActiveUser();
assert user != null;
myPropertyIndex.set(-1);
Callable<Webproperties> fetchProperties = new Callable<Webproperties>() {
@Override
public Webproperties call() throws Exception {
Analytics analytics =
new Analytics.Builder(new NetHttpTransport(), new JacksonFactory(), user.getCredential()).setApplicationName("Android Studio")
.build();
String id = account.getId();
Webproperties properties = analytics.management().webproperties().list(id).execute();
if (properties != null && properties.getItems().size() > 0) {
return properties;
}
return null;
}
};
Dispatchable<Webproperties> onPropertiesFetched = new Dispatchable<Webproperties>() {
@Override
public void dispatch(@NotNull Webproperties properties) {
myProperties.setAll(properties.getItems());
myPropertyIndex.set(0);
}
};
runInBackground(fetchProperties, onPropertiesFetched);
}
}