plugins/org.symbian.tools.wrttools/src/org/symbian/tools/wrttools/core/internal/validation/WrtApplicationValidator.java
package org.symbian.tools.wrttools.core.internal.validation;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.IRegion;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.validation.AbstractValidator;
import org.eclipse.wst.validation.ValidationResult;
import org.eclipse.wst.validation.ValidationState;
import org.eclipse.wst.validation.ValidatorMessage;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.symbian.tools.wrttools.Activator;
import org.symbian.tools.wrttools.util.CoreUtil;
import org.symbian.tools.wrttools.util.ProjectUtils;
import org.symbian.tools.wrttools.util.Util;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@SuppressWarnings("restriction")
public class WrtApplicationValidator extends AbstractValidator {
@Override
public ValidationResult validate(IResource resource, int kind,
ValidationState state, IProgressMonitor monitor) {
if (ProjectUtils.isPlist(resource)) {
return validatePlist((IFile) resource);
} else if (isProject(resource)) {
return validateProject((IProject) resource);
} else {
return null;
}
}
private ValidationResult validateProject(IProject resource) {
ValidationResult result = new ValidationResult();
try {
isPlistPresent(resource, result);
} catch (CoreException e) {
Activator.log(e);
}
return result;
}
private boolean isProject(IResource resource) {
return resource.getType() == IResource.PROJECT
&& ProjectUtils.hasWrtNature(resource.getProject());
}
private ValidationResult validatePlist(IFile resource) {
ValidationResult result = new ValidationResult();
IStructuredModel structuredModel;
try {
structuredModel = StructuredModelManager.getModelManager()
.getModelForRead(resource);
try {
if (structuredModel instanceof IDOMModel) {
IDOMModel model = (IDOMModel) structuredModel;
validateElement((IDOMElement) model.getDocument()
.getDocumentElement(), result, resource);
checkHtml(model, resource, result);
checkPlistValues(model, resource, result);
}
} finally {
if (structuredModel != null) {
structuredModel.releaseFromRead();
}
}
} catch (IOException e) {
Activator.log(e);
} catch (CoreException e) {
Activator.log(e);
}
return result;
}
private static enum PListElements {
plist, array, data, date, dict, real, integer, string, FALSE, TRUE, key, xml
};
private void validateElement(IDOMElement element, ValidationResult result,
IResource resource) {
// showData("");
PListElements[] values = PListElements.values();
boolean isValidElement = false;
for (PListElements validElement : values) {
if (validElement.toString().equalsIgnoreCase(
element.getNodeName().trim())) {
isValidElement = true;
break;
}
continue;
}
if (!isValidElement) {
Object[] arguments = { " ", element.getNodeName().trim() };
String message = MessageFormat.format(ValidatorPropMessages
.getString("plist.element.not.supported")
+ "{0}" + "{1}", arguments);
result.add(createMessage(resource, message, element
.getStartOffset(), element.getEndOffset()));
}
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
if (item.getNodeType() == Node.ELEMENT_NODE) {
validateElement((IDOMElement) item, result, resource);
}
}
}
private ValidatorMessage createMessage(IResource resource, String message,
int startOffset, int endOffset) {
ValidatorMessage msg = ValidatorMessage.create(message, resource);
msg.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
msg.setAttribute(IMarker.CHAR_START, startOffset);
msg.setAttribute(IMarker.CHAR_END, endOffset);
return msg;
}
private boolean checkHtml(IDOMModel model, IFile plist,
ValidationResult result) {
String text = model.getStructuredDocument().get();
IRegion region = CoreUtil.getIndexFileNameRegion(text);
boolean checkHtml = false;
if (region != null) {
String htmlName = text.substring(region.getOffset(), region
.getOffset()
+ region.getLength());
IFile htmlFile = null;
try {
htmlFile = getFile(plist.getProject(), new Path(htmlName), 0,
"html", "htm");
} catch (CoreException e) {
Activator.log(e);
}
if (htmlFile == null) {
Object[] arguments = { htmlName, "<>", htmlName };
String message = MessageFormat.format(ValidatorPropMessages
.getString("plist.html.element.mismatch")
+ "{0}" + "{1}" + "{2}", arguments);
result.add(createMessage(plist, message, region.getOffset(),
region.getOffset() + region.getLength()));
}
} else {
String message = ValidatorPropMessages
.getString("plist.html.element.mailHtml.missing");
ValidatorMessage msg = createMessage(plist, message, 0, 0);
setMessageOnRootElement(msg, model);
result.add(msg);
}
return checkHtml;
}
private void setMessageOnRootElement(ValidatorMessage msg, IDOMModel model) {
Element element = model.getDocument().getDocumentElement();
int begin = 0, end = 0;
if (element instanceof IDOMNode) {
IDOMNode node = (IDOMNode) element;
begin = node.getStartOffset();
end = node.getFirstStructuredDocumentRegion().getEnd();
}
msg.setAttribute(IMarker.CHAR_START, begin);
msg.setAttribute(IMarker.CHAR_END, end);
}
private IFile getFile(IContainer container, IPath path, int segment,
String... extensions) throws CoreException {
if (segment + 1 == path.segmentCount()) {
return getFile(container, path.lastSegment(), extensions);
} else {
String name = path.segment(segment).toLowerCase();
IResource[] members = container.members();
for (IResource resource : members) {
if (resource.getName().toLowerCase().equals(name)) {
if (resource.getType() == IResource.FOLDER) {
return getFile((IContainer) resource, path,
segment + 1, extensions);
}
}
}
}
return null;
}
private IFile getFile(IContainer container, String lastSegment,
String[] extensions) throws CoreException {
final Set<String> names = new TreeSet<String>();
names.add(lastSegment.toLowerCase());
for (String extension : extensions) {
names.add(lastSegment.concat(".").concat(extension).toLowerCase());
}
IResource[] members = container.members();
for (IResource resource : members) {
if (resource.getType() == IResource.FILE
&& names.contains(resource.getName().toLowerCase())
&& resource.isAccessible()) {
return (IFile) resource;
}
}
return null;
}
private void checkPlistValues(IDOMModel model, IResource plist,
ValidationResult result) {
String source = model.getStructuredDocument().get();
if (!hasAttributeValue(source, "DisplayName")) {
Object[] arguments = { " 'Display Name' ",
ValidatorPropMessages.getString("not.in.plist.file") };
String message = MessageFormat.format(ValidatorPropMessages
.getString("plist.mankey.mising")
+ "{0}" + "{1}", arguments);
ValidatorMessage msg = createMessage(plist, message, 0, 0);
setMessageOnRootElement(msg, model);
result.add(msg);
} else /* validating Widget name (Display name) */
{
Matcher matcher = CoreUtil.getPropertyLookupPattern("DisplayName")
.matcher(source);
if (matcher.find()) {
String strError = Util.validateWidgetName(matcher.group(1));
if (strError != null) {
Object[] arguments = {
" 'Display Name' ",
ValidatorPropMessages
.getString("contains.invalid.character") };
String message = MessageFormat.format(ValidatorPropMessages
.getString("plist.mankey.mising")
+ "{0}" + "{1}", arguments);
ValidatorMessage msg = createMessage(plist, message,
matcher.start(), matcher.end());
result.add(msg);
}
}
}
if (!hasAttributeValue(source, "MainHTML")) {
Object[] arguments = { " 'MainHTML ' ",
ValidatorPropMessages.getString("not.in.plist.file") };
String message = MessageFormat.format(ValidatorPropMessages
.getString("plist.mankey.mising")
+ "{0}" + "{1}", arguments);
ValidatorMessage msg = createMessage(plist, message, 0, 0);
setMessageOnRootElement(msg, model);
result.add(msg);
}
if (!hasAttributeValue(source, "Identifier")) {
Object[] arguments = { " 'Identifier ' ",
ValidatorPropMessages.getString("not.in.plist.file") };
String message = MessageFormat.format(ValidatorPropMessages
.getString("plist.mankey.mising")
+ "{0}" + "{1}", arguments);
ValidatorMessage msg = createMessage(plist, message, 0, 0);
setMessageOnRootElement(msg, model);
result.add(msg);
} else /* validating Widget Idenfier (UID) */
{
Matcher matcher = CoreUtil.getPropertyLookupPattern("Identifier")
.matcher(source);
if (matcher.find()) {
String strError = Util.validateWidgetID(matcher.group(1));
if (strError != null) {
Object[] arguments = {
" 'Identifier' ",
ValidatorPropMessages
.getString("contains.invalid.character") };
String message = MessageFormat.format(ValidatorPropMessages
.getString("plist.mankey.mising")
+ "{0}" + "{1}", arguments);
ValidatorMessage msg = createMessage(plist, message,
matcher.start(1), matcher.end(1));
result.add(msg);
}
}
}
}
private boolean hasAttributeValue(String source, String propertyName) {
Pattern pattern = CoreUtil.getPropertyLookupPattern(propertyName);
boolean hasAttr = true;
Matcher matcher = pattern.matcher(source);
if (!matcher.find()) {
hasAttr = false;
} else {
hasAttr = matcher.group(1).trim().length() > 0;
}
return hasAttr;
}
private void isPlistPresent(IProject project, ValidationResult result)
throws CoreException {
IResource[] members = project.members();
for (IResource resource : members) {
if (ProjectUtils.isPlist(resource)) {
return;
}
}
ValidatorMessage msg = ValidatorMessage.create(ValidatorPropMessages
.getString("plist.File.Not.Present"), project);
msg.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
result.add(msg);
}
}