/*
* 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.manifest.dom;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
/**
* Class that represents a <manifest> node on AndroidManifest.xml file
*/
public class ManifestNode extends AndroidManifestNode implements IAndroidManifestProperties
{
static
{
defaultProperties.add(PROP_XMLNS);
defaultProperties.add(PROP_PACKAGE);
defaultProperties.add(PROP_SHAREDUSERID);
defaultProperties.add(PROP_VERSIONCODE);
defaultProperties.add(PROP_VERSIONNAME);
}
/**
* Default value for xmlns:android property
*/
private static final String PROP_XMLNS_DEFAULTVALUE =
"http://schemas.android.com/apk/res/android";
/**
* The package property
*/
private String propPackage = null;
/**
* The sharedUserId property
*/
private String propSharedUserId = null;
/**
* The versionCode property
*/
private Integer propVersionCode = null;
/**
* The versionName property
*/
private String propVersionName = null;
public ManifestNode(String packageName)
{
setPackage(packageName);
}
/* (non-Javadoc)
* @see com.motorola.studio.android.model.manifest.dom.AndroidManifestNode#canContains(com.motorola.studio.android.model.manifest.dom.AndroidManifestNode.NodeType)
*/
@Override
protected boolean canContains(NodeType nodeType)
{
return (nodeType == NodeType.Application) || (nodeType == NodeType.Instrumentation)
|| (nodeType == NodeType.Permission) || (nodeType == NodeType.PermissionGroup)
|| (nodeType == NodeType.PermissionTree) || (nodeType == NodeType.UsesPermission)
|| (nodeType == NodeType.UsesFeature) || (nodeType == NodeType.UsesSdk)
|| (nodeType == NodeType.Comment) || (nodeType == NodeType.MetaData)
|| (nodeType == NodeType.Unknown);
}
/* (non-Javadoc)
* @see com.motorola.studio.android.model.manifest.dom.AndroidManifestNode#getNodeType()
*/
@Override
public NodeType getNodeType()
{
return NodeType.Manifest;
}
/* (non-Javadoc)
* @see com.motorola.studio.android.model.manifest.dom.AndroidManifestNode#getNodeProperties()
*/
@Override
public Map<String, String> getNodeProperties()
{
properties.clear();
properties.put(PROP_XMLNS, PROP_XMLNS_DEFAULTVALUE);
properties.put(PROP_PACKAGE, propPackage);
if (propSharedUserId != null)
{
properties.put(PROP_SHAREDUSERID, propSharedUserId);
}
if (propVersionCode != null)
{
properties.put(PROP_VERSIONCODE, propVersionCode.toString());
}
if (propVersionName != null)
{
properties.put(PROP_VERSIONNAME, propVersionName);
}
return properties;
}
/* (non-Javadoc)
* @see com.motorola.studio.android.model.manifest.dom.AndroidManifestNode#isNodeValid()
*/
@Override
protected boolean isNodeValid()
{
int applicationCount = 0;
boolean allAcceptable = true;
for (AndroidManifestNode child : children)
{
if (child.getNodeType() == NodeType.Application)
{
applicationCount++;
}
else if (!canContains(child.getNodeType()))
{
allAcceptable = false;
break;
}
}
return allAcceptable && (applicationCount == 1) && isValidPackageName(propPackage);
}
/**
* Checks if a package name is valid
*
* @param packageName The package name to be verified
*
* @return true if the package name is valid or false otherwise
*/
private boolean isValidPackageName(String packageName)
{
boolean isValid = false;
String[] parts = packageName.split("\\.");
if (parts.length > 1)
{
isValid = true;
for (String part : parts)
{
isValid &= part.length() > 0;
}
}
return isValid;
}
/**
* Sets the package property value.
*
* @param packageName the package property value
*/
public void setPackage(String packageName)
{
Assert.isLegal(packageName != null);
propPackage = packageName;
}
/**
* Gets the package property value.
*
* @return the package property value
*/
public String getPackageName()
{
return propPackage;
}
/**
* Sets the android:sharedUserId property value. Set it to null
* if you do not want to use it.
*
* @param sharedUserId the sharedUserId property value
*/
public void setSharedUserId(String sharedUserId)
{
propSharedUserId = sharedUserId;
}
/**
* Gets the android:sharedUserId property value.
*
* @return the android:sharedUserId property value
*/
public String getSharedUserId()
{
return propSharedUserId;
}
/**
* Sets the android:versionCode property value. Set it to null
* if you do not want to use it.
*
* @param versionCode the versionCode property value
*/
public void setVersionCode(Integer versionCode)
{
propVersionCode = versionCode;
}
/**
* Gets the android:versionCode property value.
*
* @return the android:versionCode property value.
*/
public Integer getVersionCode()
{
return propVersionCode;
}
/**
* Sets the android:versionName property value. Set it to null
* if you do not want to use it.
*
* @param versionName the versionName property value
*/
public void setVersionName(String versionName)
{
propVersionName = versionName;
}
/**
* Gets the android:versionName property value.
*
* @return the android:versionName property value.
*/
public String getVersionName()
{
return propVersionName;
}
/**
* Retrieves the application node. Creates a new if it does not exist.
*
* @return the application node
*/
public ApplicationNode getApplicationNode()
{
ApplicationNode applicationNode = null;
for (AndroidManifestNode appNode : getAllChildrenFromType(NodeType.Application))
{
applicationNode = (ApplicationNode) appNode;
break;
}
if (applicationNode == null)
{
applicationNode = new ApplicationNode("");
addChild(applicationNode);
}
return applicationNode;
}
/**
* Adds an Instrumentation Node to the Manifest Node
*
* @param instrumentation The Instrumentation Node
*/
public void addInstrumentationNode(InstrumentationNode instrumentation)
{
if (instrumentation != null)
{
if (!children.contains(instrumentation))
{
children.add(instrumentation);
}
}
}
/**
* Retrieves all Instrumentation Nodes from the Manifest Node
*
* @return all Instrumentation Nodes from the Manifest Node
*/
public List<InstrumentationNode> getInstrumentationNodes()
{
List<InstrumentationNode> instrumentations = new LinkedList<InstrumentationNode>();
for (AndroidManifestNode node : getAllChildrenFromType(NodeType.Instrumentation))
{
instrumentations.add((InstrumentationNode) node);
}
return instrumentations;
}
/**
* Removes an Instrumentation Node from the Manifest Node
*
* @param instrumentation the Instrumentation Node to be removed
*/
public void removeInstrumentationNode(InstrumentationNode instrumentation)
{
if (instrumentation != null)
{
children.remove(instrumentation);
}
}
/**
* Adds a Permission Node to the Manifest Node
*
* @param permission The Permission Node
*/
public void addPermissionNode(PermissionNode permission)
{
if (permission != null)
{
if (!children.contains(permission))
{
children.add(permission);
}
}
}
/**
* Retrieves all Permission Nodes from the Manifest Node
*
* @return all Permission Nodes from the Manifest Node
*/
public List<PermissionNode> getPermissionNodes()
{
List<PermissionNode> permissions = new LinkedList<PermissionNode>();
for (AndroidManifestNode node : getAllChildrenFromType(NodeType.Permission))
{
permissions.add((PermissionNode) node);
}
return permissions;
}
/**
* Removes a Permission Node from the Manifest Node
*
* @param permission the Permission Node to be removed
*/
public void removePermissionNode(PermissionNode permission)
{
if (permission != null)
{
children.remove(permission);
}
}
/**
* Adds a Permission Group Node to the Manifest Node
*
* @param permissionGroup The Permission Group Node
*/
public void addPermissionGroupNode(PermissionGroupNode permissionGroup)
{
if (permissionGroup != null)
{
if (!children.contains(permissionGroup))
{
children.add(permissionGroup);
}
}
}
/**
* Retrieves all Permission Group Nodes from the Manifest Node
*
* @return all Permission Group Nodes from the Manifest Node
*/
public List<PermissionGroupNode> getPermissionGroupNodes()
{
List<PermissionGroupNode> permissionGroups = new LinkedList<PermissionGroupNode>();
for (AndroidManifestNode node : getAllChildrenFromType(NodeType.PermissionGroup))
{
permissionGroups.add((PermissionGroupNode) node);
}
return permissionGroups;
}
/**
* Removes a Permission Group Node from the Manifest Node
*
* @param permissionGroup the Permission Group Node to be removed
*/
public void removePermissionGroupNode(PermissionGroupNode permissionGroup)
{
if (permissionGroup != null)
{
children.remove(permissionGroup);
}
}
/**
* Adds a Permission Tree Node to the Manifest Node
*
* @param permissionTree The Permission Tree Node
*/
public void addPermissionTreeNode(PermissionTreeNode permissionTree)
{
if (permissionTree != null)
{
if (!children.contains(permissionTree))
{
children.add(permissionTree);
}
}
}
/**
* Retrieves all Permission Tree Nodes from the Manifest Node
*
* @return all Permission Tree Nodes from the Manifest Node
*/
public List<PermissionTreeNode> getPermissionTreeNodes()
{
List<PermissionTreeNode> permissionTrees = new LinkedList<PermissionTreeNode>();
for (AndroidManifestNode node : getAllChildrenFromType(NodeType.PermissionTree))
{
permissionTrees.add((PermissionTreeNode) node);
}
return permissionTrees;
}
/**
* Removes a Permission Tree Node from the Manifest Node
*
* @param permissionTree the Permission Tree Node to be removed
*/
public void removePermissionTreeNode(PermissionTreeNode permissionTree)
{
if (permissionTree != null)
{
children.remove(permissionTree);
}
}
/**
* Adds an Uses Permission Node to the Manifest Node
*
* @param usesPermission The Uses Permission Node
*/
public void addUsesPermissionNode(UsesPermissionNode usesPermission)
{
if (usesPermission != null)
{
if (!children.contains(usesPermission))
{
addBeforeApplicationNode(usesPermission);
}
}
}
/**
* Retrieves all Uses Permission Nodes from the Manifest Node
*
* @return all Uses Permission Nodes from the Manifest Node
*/
public List<UsesPermissionNode> getUsesPermissionNodes()
{
List<UsesPermissionNode> usesPermissions = new LinkedList<UsesPermissionNode>();
for (AndroidManifestNode node : getAllChildrenFromType(NodeType.UsesPermission))
{
usesPermissions.add((UsesPermissionNode) node);
}
return usesPermissions;
}
/**
* Removes an Uses Permission Node from the Manifest Node
*
* @param usesPermission the Uses Permission Node to be removed
*/
public void removeUsesPermissionNode(UsesPermissionNode usesPermission)
{
if (usesPermission != null)
{
children.remove(usesPermission);
}
}
/**
* Removes an Used Permission from the Manifest Node.
* Convenience method to remove an used permission using its name.
* Note: all uses-permission nodes of the given permission are removed.
*
* @param permission the used permission name to be removed
* @return the number of uses-permission nodes removed
*/
public int removeUsesPermissionNode(String permission)
{
int nodesRemoved = 0;
for (UsesPermissionNode node : getUsesPermissionNodes())
{
if (node.getName().equals(permission))
{
removeUsesPermissionNode(node);
nodesRemoved++;
}
}
return nodesRemoved;
}
/* (non-Javadoc)
* @see com.motorola.studio.android.model.manifest.dom.AndroidManifestNode#getSpecificNodeErrors()
*/
@Override
protected List<IStatus> getSpecificNodeProblems()
{
return null;
}
/**
* Adds an Uses Feature Node to the Manifest Node
*
* @param usesFeature The Uses Feature Node
*/
public void addUsesFeatureNode(UsesFeatureNode usesFeature)
{
if (usesFeature != null)
{
if (!children.contains(usesFeature))
{
addBeforeApplicationNode(usesFeature);
}
}
}
/**
* Retrieves Uses Feature Node from the Manifest Node
*
* @return null if no node if the featureName is found, or the refence to the node if it exists
*/
public UsesFeatureNode getUsesFeatureNode(String featureName)
{
UsesFeatureNode usesFeature = null;
for (AndroidManifestNode node : getAllChildrenFromType(NodeType.UsesFeature))
{
if ((node.getNodeProperties() != null)
&& node.getNodeProperties().containsKey("android:name")
&& node.getNodeProperties().get("android:name").equals(featureName))
{
usesFeature = (UsesFeatureNode) node;
break;
}
}
return usesFeature;
}
/**
* Retrieves Uses SDK Node from the Manifest Node
*
* @return null if no uses-sdk node is found, or the refence to the node if it exists
*/
public UsesSDKNode getUsesSdkNode()
{
UsesSDKNode usesSDKNode = null;
for (AndroidManifestNode node : getAllChildrenFromType(NodeType.UsesSdk))
{
if (node instanceof UsesSDKNode)
{
//get the first node - it should NOT have more than once
usesSDKNode = (UsesSDKNode) node;
break;
}
}
return usesSDKNode;
}
/**
* Adds an Uses SDK Node to the Manifest Node
*
* @param usesSDK The Uses SDK Node
*/
public void addUsesSdkNode(UsesSDKNode usesSdk)
{
if (usesSdk != null)
{
if (!children.contains(usesSdk))
{
addBeforeApplicationNode(usesSdk);
}
}
}
/**
* Adds before application node (if it exists), otherwise adds after
* @param node
*/
private void addBeforeApplicationNode(AndroidManifestNode node)
{
ApplicationNode applicationNode = getApplicationNode();
if (applicationNode != null)
{
int appNodeIdx = children.indexOf(applicationNode);
children.add(appNodeIdx, node);
}
else
{
children.add(node);
}
}
}