| package org.eclipse.jst.pagedesigner.itemcreation.internal; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.jst.jsf.common.metadata.Entity; |
| import org.eclipse.jst.jsf.common.metadata.MetadataFactory; |
| import org.eclipse.jst.jsf.common.metadata.Model; |
| import org.eclipse.jst.jsf.common.metadata.Trait; |
| import org.eclipse.jst.jsf.common.metadata.internal.TraitValueHelper; |
| import org.eclipse.jst.jsf.common.metadata.query.IMetaDataModelContext; |
| import org.eclipse.jst.jsf.common.metadata.query.MetaDataQueryHelper; |
| import org.eclipse.jst.jsf.core.internal.tld.ITLDConstants; |
| import org.eclipse.jst.pagedesigner.IHTMLConstants; |
| import org.eclipse.jst.pagedesigner.dom.DOMPositionHelper; |
| import org.eclipse.jst.pagedesigner.dom.IDOMPosition; |
| import org.eclipse.jst.pagedesigner.dom.JSFValidatorSupport; |
| import org.eclipse.jst.pagedesigner.dom.ValidatorSupport; |
| import org.eclipse.jst.pagedesigner.editors.palette.TagToolPaletteEntry; |
| import org.eclipse.jst.pagedesigner.editors.palette.impl.PaletteElementTemplateHelper; |
| import org.eclipse.jst.pagedesigner.editors.palette.paletteinfos.PaletteInfo; |
| import org.eclipse.jst.pagedesigner.editors.palette.paletteinfos.PaletteInfos; |
| import org.eclipse.jst.pagedesigner.editors.palette.paletteinfos.PaletteInfosFactory; |
| import org.eclipse.jst.pagedesigner.editors.palette.paletteinfos.TagCreationAttribute; |
| import org.eclipse.jst.pagedesigner.editors.palette.paletteinfos.TagCreationInfo; |
| import org.eclipse.jst.pagedesigner.itemcreation.ITagCreator; |
| import org.eclipse.jst.pagedesigner.utils.BodyHelper; |
| import org.eclipse.jst.pagedesigner.utils.JSPUtil; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; |
| import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; |
| import org.w3c.dom.Element; |
| |
| /** |
| * {@link ITagCreator} used by the Web Page Editor palette. |
| * |
| * Uses org.eclipse.jst.jsf.common.metadata |
| */ |
| public class DefaultTagCreator implements ITagCreator { |
| |
| private static final QName _qnameHTMLForm = new QName(CMDocType.HTML_DOC_TYPE, IHTMLConstants.TAG_FORM); |
| |
| /** |
| * The {@link TagToolPaletteEntry} being used |
| */ |
| protected TagToolPaletteEntry _tagItem; |
| /** |
| * The {@link IMetaDataModelContext} for the tag creation |
| */ |
| protected IMetaDataModelContext _modelContext; |
| /** |
| * The tag {@link Entity} being created |
| */ |
| private Entity _tagEntity; |
| |
| /** |
| * Construct a tag creator for the _modelContext |
| * @param _modelContext |
| */ |
| public DefaultTagCreator(IMetaDataModelContext modelContext) { |
| this._modelContext = modelContext; |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jst.pagedesigner.itemcreation.ITagCreator#createTag(org.eclipse.jst.pagedesigner.editors.palette.TagToolPaletteEntry, org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel, org.eclipse.jst.pagedesigner.dom.IDOMPosition) |
| */ |
| public Element createTag(TagToolPaletteEntry tagToolPaletteEntry, IDOMModel model, IDOMPosition domPosition) { |
| this._tagItem = tagToolPaletteEntry; |
| |
| IDOMPosition position = preAdjustPositionForNecessaryContainers(model, domPosition); |
| if (position == null)//throw exception? |
| return null; |
| |
| String uri = getURI(); |
| String defaultPrefix = getDefaultPrefix(); |
| String prefix = getPrefix(uri, model, defaultPrefix); |
| |
| Element ele = createElement(model, prefix); |
| if (ele == null)//throw exception? |
| return null; |
| |
| applyTemplate(model, ele); |
| applyRequiredAttrs(ele); |
| |
| addTagToContainer(position, ele); |
| |
| return ele; |
| } |
| |
| /** |
| * @param model |
| * @param prefix |
| * @return {@link Element} |
| */ |
| protected Element createElement(IDOMModel model, String prefix){ |
| Element ele = model.getDocument().createElement(_tagItem.getTagName()); |
| if (ele == null) |
| return null; |
| |
| //ugly... fix me |
| |
| // XXX: we are using "startsWith("directive.")" to test whether |
| // should setJSPTag, this |
| // maybe is not the best way. Need check whether SSE have special |
| // API for it. |
| if (ITLDConstants.URI_JSP.equals(getURI()) |
| && (ele.getLocalName().startsWith("directive.") |
| || "declaration".equals(ele.getLocalName()) |
| || "expression".equals(ele.getLocalName()) || "scriptlet" |
| .equals(ele.getLocalName()))) { |
| // it is a jsp tag |
| ((IDOMElement) ele).setJSPTag(true); |
| } |
| if (prefix != null) |
| ele.setPrefix(prefix); |
| return ele; |
| } |
| /** |
| * @param position |
| * @param tagElement |
| */ |
| protected void addTagToContainer(IDOMPosition position, Element tagElement) { |
| if (position == null || position.getContainerNode() == null) { |
| return; |
| } |
| |
| if (position.getNextSiblingNode() == null) { |
| position.getContainerNode().appendChild(tagElement); |
| } else { |
| position.getContainerNode().insertBefore(tagElement, |
| position.getNextSiblingNode()); |
| } |
| |
| } |
| |
| /** |
| * Return position for tag after all necessary containers are created. |
| * If nnecessary containers cannot be created and do not exist for any reason, implementer should return null |
| * to signal that the tag creation should not occur. |
| * @param model |
| * @param domPosition |
| * @return position after necessary containers are created |
| */ |
| protected IDOMPosition preAdjustPositionForNecessaryContainers(IDOMModel model, |
| IDOMPosition domPosition) { |
| |
| IDOMPosition position = DOMPositionHelper.splitText(domPosition); |
| |
| position = BodyHelper |
| .adjustInsertPosition(getURI(), getLocalTagName(), position); |
| |
| position = createContainers(position); |
| if (position == null) { |
| // user cancelled |
| return null; |
| } |
| |
| // because the next call of getPrefix() may insert new taglib node |
| // into the document, if we use the normal |
| // DOMPositin which use index, maybe it will be invalidated by the |
| // new taglib node. So use RefPosition here. |
| return DOMPositionHelper.toDOMRefPosition(position); |
| } |
| |
| /** |
| * @param position |
| * @return position after creating required containers |
| */ |
| protected IDOMPosition createContainers(IDOMPosition position) { |
| |
| //FIX ME - should be done in subclass |
| if (isJSFComponent()) { |
| return JSFValidatorSupport.prepareInsertJSFComponent(position, getURI(), getLocalTagName(), isHTMLFormRequired()); |
| } |
| else if (isHTMLFormRequired()){ |
| boolean hasform = ValidatorSupport.checkContainer(position, _qnameHTMLForm); |
| IDOMPosition newPosition = position; |
| if (!hasform) { |
| newPosition = ValidatorSupport |
| .insertContainer(position, _qnameHTMLForm); |
| if (newPosition == null) { |
| newPosition = position; |
| } |
| } |
| return newPosition; |
| } |
| return position; |
| } |
| |
| private boolean isJSFComponent() { |
| Model model = MetaDataQueryHelper.getModel(_modelContext); |
| Trait t = MetaDataQueryHelper.getTrait(model, "is-jsf-component-library"); |
| if (t != null) |
| return TraitValueHelper.getValueAsBoolean(t); |
| |
| return false; |
| } |
| |
| /** |
| * @return convenience method returning default prefix to be used by the tag item |
| */ |
| private String getDefaultPrefix() { |
| return _tagItem.getDefaultPrefix(); |
| } |
| |
| /** |
| * @return convenience method returning uri of the tag item's library |
| */ |
| private String getURI() { |
| return _tagItem.getURI(); |
| } |
| |
| /** |
| * @return convenience method returning the tag name without prefix |
| * |
| */ |
| private String getLocalTagName(){ |
| return _tagItem.getTagName(); |
| } |
| /** |
| * Add required attributes and default values, if set, to the created tag element |
| * @param element |
| */ |
| protected void applyRequiredAttrs(Element element) { |
| TagCreationInfo info = getTagCreationInfo(); |
| if (info != null){ |
| EList list = info.getAttributes(); |
| if (list != null) { |
| for (Iterator it = list.iterator(); it.hasNext();) { |
| TagCreationAttribute attr = (TagCreationAttribute)it.next(); |
| element.setAttribute(attr.getId(), (attr.getValue() == null ? "" : attr.getValue())); |
| } |
| } |
| } |
| } |
| |
| /** |
| * If TagCreationInfo is defined for the tag element, apply the template if defined |
| * @param model |
| * @param tagElement |
| */ |
| protected void applyTemplate(IDOMModel model, Element tagElement) { |
| TagCreationInfo tagCreationInfo = getTagCreationInfo(); |
| if (tagCreationInfo != null) |
| PaletteElementTemplateHelper.applyTemplate(model, tagElement, getTagToolItem(), tagCreationInfo); |
| } |
| |
| /** |
| * @return {@link TagCreationInfo} for the tag entity |
| */ |
| protected TagCreationInfo getTagCreationInfo(){ |
| Model model = MetaDataQueryHelper.getModel(_modelContext); |
| if (model != null){ |
| Trait trait = MetaDataQueryHelper.getTrait(model, PaletteInfos.TRAIT_ID); |
| if (trait != null){ |
| PaletteInfos pis = (PaletteInfos)trait.getValue(); |
| PaletteInfo pi = pis.findPaletteInfoById(_tagItem.getId()); |
| if (pi != null){ |
| return pi.getTagCreation(); |
| } |
| } |
| //tag-creation trait on entity directly? |
| Entity tag = getTagEntity(); |
| if (tag != null){//metadata exists |
| trait = MetaDataQueryHelper.getTrait(tag, "tag-create"); |
| if (trait != null && trait.getValue() != null){ |
| return (TagCreationInfo)trait.getValue(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @return the {@link TagToolPaletteEntry} |
| */ |
| protected TagToolPaletteEntry getTagToolItem(){ |
| return _tagItem; |
| } |
| |
| |
| /** |
| * Returns the ns prefix for the tag and also creates taglib reference if necessary |
| * @param uri |
| * @param model |
| * @param suggested |
| * @return prefix to use |
| */ |
| protected String getPrefix(String uri, IDOMModel model, |
| String suggested) { |
| if (ITLDConstants.URI_HTML.equalsIgnoreCase(uri) |
| || ITLDConstants.URI_JSP.equalsIgnoreCase(uri) |
| || CMDocType.JSP11_DOC_TYPE.equalsIgnoreCase(uri)) { |
| return null; |
| } |
| |
| // now handles custom tag lib |
| return JSPUtil.getOrCreatePrefix(model, uri, suggested); |
| } |
| |
| /** |
| * @param tag |
| * @return a "create-tag" {@link Trait} for the tag. May be null there are no required attrs. |
| */ |
| protected Trait createRequiredAttrTraits(CMElementDeclaration tag) { |
| |
| List reqs = new ArrayList(); |
| for (Iterator it=tag.getAttributes().iterator();it.hasNext();){ |
| CMAttributeDeclaration attr = (CMAttributeDeclaration)it.next(); |
| if (attr.getUsage() == CMAttributeDeclaration.REQUIRED){ |
| reqs.add(attr); |
| } |
| } |
| if (reqs.size() > 0) |
| return internalCreateTagCreateAttributes(reqs); |
| |
| return null; |
| } |
| |
| private Trait internalCreateTagCreateAttributes(List reqs) { |
| Trait t = MetadataFactory.eINSTANCE.createTrait(); |
| t.setId("create-trait"); |
| |
| TagCreationInfo info = PaletteInfosFactory.eINSTANCE.createTagCreationInfo(); |
| for (Iterator it=reqs.iterator();it.hasNext();){ |
| TagCreationAttribute attrInfo = PaletteInfosFactory.eINSTANCE.createTagCreationAttribute(); |
| CMAttributeDeclaration attr = (CMAttributeDeclaration)it.next(); |
| attrInfo.setId(attr.getAttrName()); |
| attrInfo.setValue("");//TODO: use default value? |
| info.getAttributes().add(attrInfo); |
| } |
| t.setValue(info); |
| return t; |
| } |
| |
| /** |
| * @return flag indicating that html form container ancestor is required |
| */ |
| protected boolean isHTMLFormRequired() { |
| Trait t = MetaDataQueryHelper.getTrait(getTagEntity(), "requires-html-form"); |
| if (t != null) |
| return TraitValueHelper.getValueAsBoolean(t); |
| |
| return false; |
| } |
| |
| /** |
| * @return the {@link Entity} for this tag element being created |
| */ |
| protected Entity getTagEntity() { |
| if (_tagEntity == null){ |
| _tagEntity = MetaDataQueryHelper.getEntity(_modelContext, _tagItem.getTagName()); |
| |
| } |
| return _tagEntity; |
| } |
| } |