// offsets AND if it possesses a value
boolean attrAtLocationHasValue = false;
boolean proposalNeedsSpace = false;
NamedNodeMap attrs = node.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
AttrImpl existingAttr = (AttrImpl) attrs.item(i);
ITextRegion name = existingAttr.getNameRegion();
if (name != null && (sdRegion.getStartOffset(name) <= contentAssistRequest.getReplacementBeginPosition()) &&
(sdRegion.getStartOffset(name) + name.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength()) &&
(existingAttr.getValueRegion() != null)) {
// selected region is attribute name
if (cursorOffset >= sdRegion.getStartOffset(name) && contentAssistRequest.getReplacementLength() != 0)
attrAtLocationHasValue = true;
// propose new attribute, cursor is at the start of another attribute name
else if (cursorOffset == sdRegion.getStartOffset(name))
proposalNeedsSpace = true;
break;
}
}
// only add proposals for the attributes whose names begin with the matchstring
if (attributes != null) {
for (int i = 0; i < attributes.getLength(); i++) {
CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attributes.item(i);
if(validModelQueryNode(attrDecl)) {
int isRequired = 0;
if (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) {
isRequired = XMLRelevanceConstants.R_REQUIRED;
}
boolean showAttribute = true;
showAttribute = showAttribute && beginsWith(getRequiredName(node, attrDecl), matchString.trim());
AttrImpl attr = (AttrImpl) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
ITextRegion nameRegion = attr != null ? attr.getNameRegion() : null;
// nameRegion.getEndOffset() + 1 is required to allow for
// matches against the full name of an existing Attr
showAttribute = showAttribute && ((attr == null) || nameRegion == null ||
((nameRegion != null) &&
(sdRegion.getStartOffset(nameRegion) <