/*
* Copyright (C) 2012 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.motorola.studio.android.model;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.osgi.util.NLS;
import com.motorola.studio.android.codeutils.CodeUtilsActivator;
import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS;
import com.motorola.studio.android.common.IAndroidConstants;
import com.motorola.studio.android.common.exception.AndroidException;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorola.studio.android.common.log.UsageDataConstants;
import com.motorola.studio.android.manifest.AndroidProjectManifestFile;
import com.motorola.studio.android.model.java.ContentProviderClass;
import com.motorola.studio.android.model.manifest.AndroidManifestFile;
import com.motorola.studio.android.model.manifest.dom.ApplicationNode;
import com.motorola.studio.android.model.manifest.dom.IntentFilterNode;
import com.motorola.studio.android.model.manifest.dom.ManifestNode;
import com.motorola.studio.android.model.manifest.dom.ProviderNode;
import com.motorola.studio.android.model.manifest.dom.UsesPermissionNode;
import com.motorola.studio.android.model.resources.ResourceFile;
import com.motorola.studio.android.model.resources.types.AbstractResourceNode.NodeType;
import com.motorola.studio.android.model.resources.types.ResourcesNode;
import com.motorola.studio.android.model.resources.types.StringNode;
import com.motorola.studio.android.resources.AndroidProjectResources;
/**
* ContentProvider Model
*/
public class ContentProvider extends BuildingBlockModel
{
private static final String PROVIDER_RESOURCE_LABEL_SUFFIX = "ContentProviderLabel";
private final List<String> authoritiesList = new LinkedList<String>();
private static final int MANIFEST_UPDATING_STEPS = 6;
private static final int RESOURCES_UPDATING_STEPS = 3;
/**
* Constructor for Content Provider.
*/
public ContentProvider()
{
super(IAndroidConstants.CLASS_CONTENTPROVIDER);
}
/*
* (non-Javadoc)
* @see com.motorola.studio.android.model.BuildingBlockModel#getStatus()
*/
@Override
public IStatus getStatus()
{
return getMostSevere(new IStatus[]
{
super.getStatus(), getAuthorityStatus()
});
}
/**
* Return Authority Status
* @see #getStatus()
* @return
*/
private IStatus getAuthorityStatus()
{
IStatus status = new Status(IStatus.OK, CodeUtilsActivator.PLUGIN_ID, null);
if (authoritiesList.isEmpty())
{
status =
new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID,
CodeUtilsNLS.ERR_ContentProvider_InvalidAuthoritySelection);
}
return status;
}
/*
* (non-Javadoc)
* @see com.motorola.studio.android.model.IWizardModel#needMoreInformation()
*/
public boolean needMoreInformation()
{
return false;
}
/**
* Create the content provider class and add it to the manifest file.
* @return True if the content provider class was successfully create and added to the manifest file. Otherwise, return false.
* */
public boolean save(IWizardContainer container, IProgressMonitor monitor)
throws AndroidException
{
boolean classCreated = createProviderClass(monitor);
boolean addedOnManifest = false;
if (classCreated)
{
addedOnManifest = createProviderOnManifest(monitor);
}
// Logs all permissions used in UDC log
saveUsedPermissions(container, monitor);
return classCreated && addedOnManifest;
}
/*
* Logs to UDC all permissions used
*/
private boolean saveUsedPermissions(IWizardContainer container, IProgressMonitor monitor)
throws AndroidException
{
StringBuffer permissionList = new StringBuffer("Added building block permissions: ");
int selectedPermissionsSize = getIntentFilterPermissionsAsArray().length;
for (int i = 0; i < selectedPermissionsSize; i++)
{
String permission = getIntentFilterPermissionsAsArray()[i];
permissionList.append(permission);
if (i < (selectedPermissionsSize - 1))
{
permissionList.append(", ");
}
}
if (selectedPermissionsSize > 0)
{
// Logs to UDC the permissions selected
StudioLogger.collectUsageData(
UsageDataConstants.WHAT_BUILDINGBLOCK_PERMISSION, //$NON-NLS-1$
UsageDataConstants.KIND_BUILDINGBLOCK_PERMISSION,
"permissions: " + permissionList.toString(), //$NON-NLS-1$
CodeUtilsActivator.PLUGIN_ID, CodeUtilsActivator.getDefault().getBundle()
.getVersion().toString());
}
return true;
}
/**
* Return default authority.
* @return
*/
public String getDefaultAuthority()
{
IPackageFragment packageFragment = getPackageFragment();
String name = getName();
String defaultAuthority = "";
if ((name != null) && (packageFragment != null))
{
defaultAuthority = packageFragment.getElementName() + "." + name.toLowerCase();
}
return defaultAuthority;
}
/**
* Remove Authority
* @param authority
*/
public void removeAuthority(String authority)
{
authoritiesList.remove(authority);
}
/**
* Add Authority
* @param authority
*/
public void addAuthority(String authority)
{
authoritiesList.add(authority);
}
/**
* Return Authorities
* @return
*/
public List<String> getAuthoritiesList()
{
return authoritiesList;
}
/*
* Creates the Content Provider java class
*
* @param monitor the progress monitor
*
* @return true if the class has been created or false otherwise
* @throws AndroidException
*/
private boolean createProviderClass(IProgressMonitor monitor) throws AndroidException
{
boolean created = false;
String firstAuthority = "";
monitor.subTask(CodeUtilsNLS.UI_ContentProvider_CreatingTheContentProviderJavaClass);
for (String auth : getAuthoritiesList())
{
firstAuthority = auth;
break;
}
ContentProviderClass providerClass =
new ContentProviderClass(getName(), getPackageFragment().getElementName(),
firstAuthority);
try
{
createJavaClassFile(providerClass, monitor);
created = true;
}
catch (JavaModelException e)
{
String errMsg =
NLS.bind(CodeUtilsNLS.EXC_ContentProvider_CannotCreateTheContentProviderClass,
getName(), e.getLocalizedMessage());
throw new AndroidException(errMsg);
}
catch (AndroidException e)
{
String errMsg =
NLS.bind(CodeUtilsNLS.EXC_ContentProvider_CannotCreateTheContentProviderClass,
getName(), e.getLocalizedMessage());
throw new AndroidException(errMsg);
}
return created;
}
/*
* Creates the Content Provider class entry on AndroidManifest.xml file
*
* @param monitor the progress monitor
*
* @return true if the entry has been added or false otherwise
* @throws AndroidException
*/
private boolean createProviderOnManifest(IProgressMonitor monitor) throws AndroidException
{
boolean created = false;
try
{
int totalWork = MANIFEST_UPDATING_STEPS + RESOURCES_UPDATING_STEPS;
monitor.beginTask("", totalWork);
monitor.subTask(CodeUtilsNLS.UI_Common_UpdatingTheAndroidManifestXMLFile);
AndroidManifestFile androidManifestFile =
AndroidProjectManifestFile.getFromProject(getProject());
monitor.worked(1);
ManifestNode manifestNode =
androidManifestFile != null ? androidManifestFile.getManifestNode() : null;
ApplicationNode applicationNode =
manifestNode != null ? manifestNode.getApplicationNode() : null;
monitor.worked(1);
if (applicationNode != null)
{
// Adds the added permission nodes to manifest file
List<String> permissionsNames = new ArrayList<String>();
for (UsesPermissionNode i : manifestNode.getUsesPermissionNodes())
{
permissionsNames.add(i.getName());
}
for (String intentFilterPermission : getIntentFilterPermissionsAsArray())
{
if (!permissionsNames.contains(intentFilterPermission))
{
manifestNode.addChild(new UsesPermissionNode(intentFilterPermission));
}
}
boolean providerExists = false;
String classQualifier =
(getPackageFragment().getElementName()
.equals(manifestNode.getPackageName()) ? "" : getPackageFragment()
.getElementName())
+ ".";
for (ProviderNode providerNode : applicationNode.getProviderNodes())
{
if (providerNode.getName().equals(getName()))
{
providerExists = true;
break;
}
}
monitor.worked(1);
String[] authorities = new String[getAuthoritiesList().size()];
authorities = getAuthoritiesList().toArray(authorities);
if (!providerExists)
{
ProviderNode providerNode =
new ProviderNode(classQualifier + getName(), authorities[0]);
String providerLabel = createProviderLabel(monitor);
if (providerLabel != null)
{
providerNode.setLabel(AndroidProjectResources.STRING_CALL_PREFIX
+ providerLabel);
}
IntentFilterNode intentFilterNode = new IntentFilterNode();
for (int i = 1; i < authorities.length; i++)
{
providerNode.addAuthority(authorities[i]);
}
if (intentFilterNode.getChildren().length > 0)
{
providerNode.addIntentFilterNode(intentFilterNode);
}
applicationNode.addProviderNode(providerNode);
monitor.worked(1);
monitor.subTask(CodeUtilsNLS.UI_Common_SavingTheAndroidManifestXMLFile);
AndroidProjectManifestFile.saveToProject(getProject(), androidManifestFile,
true);
created = true;
monitor.worked(1);
}
}
}
catch (AndroidException e)
{
String errMsg =
NLS.bind(CodeUtilsNLS.EXC_ContentProvider_CannotUpdateTheManifestFile,
getName(), e.getLocalizedMessage());
throw new AndroidException(errMsg);
}
catch (CoreException e)
{
String errMsg =
NLS.bind(CodeUtilsNLS.EXC_ContentProvider_CannotUpdateTheManifestFile,
getName(), e.getLocalizedMessage());
throw new AndroidException(errMsg);
}
finally
{
monitor.done();
}
return created;
}
/*
* Adds the Content Provider label value on the strings resource file
*
* @param monitor the progress monitor
*
* @return The label value if it has been added to the strings resource file or null otherwise
* @throws AndroidException
*/
private String createProviderLabel(IProgressMonitor monitor) throws AndroidException
{
String resLabel = null;
if ((getLabel() != null) && (getLabel().trim().length() > 0))
{
try
{
monitor.subTask(CodeUtilsNLS.UI_Common_UpdatingTheStringsResourceFile);
ResourceFile stringsFile =
AndroidProjectResources.getResourceFile(getProject(), NodeType.String);
monitor.worked(1);
if (stringsFile.getResourcesNode() == null)
{
stringsFile.addResourceEntry(new ResourcesNode());
}
resLabel =
stringsFile.getNewResourceName(getName() + PROVIDER_RESOURCE_LABEL_SUFFIX);
StringNode strNode = new StringNode(resLabel);
strNode.setNodeValue(getLabel());
stringsFile.getResourcesNode().addChildNode(strNode);
monitor.worked(1);
AndroidProjectResources
.saveResourceFile(getProject(), stringsFile, NodeType.String);
monitor.worked(1);
}
catch (CoreException e)
{
String errMsg =
NLS.bind(
CodeUtilsNLS.EXC_ContentProvider_CannotCreateTheContentProviderLabel,
e.getLocalizedMessage());
throw new AndroidException(errMsg);
}
catch (AndroidException e)
{
String errMsg =
NLS.bind(
CodeUtilsNLS.EXC_ContentProvider_CannotCreateTheContentProviderLabel,
e.getLocalizedMessage());
throw new AndroidException(errMsg);
}
}
return resLabel;
}
/**
* Check if contains authorities.
* @param authority
* @return
*/
public boolean containsAuthority(String authority)
{
return authoritiesList.contains(authority);
}
}