blob: 9258b826b1217f40f999724771b701d5b0f3398a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.editors.palette.impl;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IProject;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jst.jsf.common.metadata.Entity;
import org.eclipse.jst.jsf.common.metadata.Model;
import org.eclipse.jst.jsf.common.metadata.Trait;
import org.eclipse.jst.jsf.common.metadata.internal.IImageDescriptorProvider;
import org.eclipse.jst.jsf.common.metadata.internal.IMetaDataSourceModelProvider;
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.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration;
import org.eclipse.jst.pagedesigner.IHTMLConstants;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.editors.palette.IPaletteItemManager;
import org.eclipse.jst.pagedesigner.editors.palette.TagToolPaletteEntry;
import org.eclipse.jst.pagedesigner.editors.palette.paletteinfos.PaletteInfo;
import org.eclipse.jst.pagedesigner.editors.palette.paletteinfos.PaletteInfos;
import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocument;
import org.eclipse.wst.html.core.internal.contentmodel.JSPCMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
/**
* Helper class.
*
* @author mengbo
*/
public class PaletteHelper {
// pattern to strip all <x> and </x> HTML tags
final private static Pattern removeHTMLTags = Pattern.compile("<[/?\\w\\s=\"\\.\\#]+>");
// pattern to find all runs of spaces longer than one
final private static Pattern trimInteriorWhitespace = Pattern.compile("[ ]+");
// pattern to find all new lines for removal
final private static Pattern removeNewLines = Pattern.compile("[\n]");
private final static ImageDescriptor DEFAULT_SMALL_ICON = PDPlugin
.getDefault().getImageDescriptor(
"palette/GENERIC/small/PD_Palette_Default.gif");
private final static ImageDescriptor DEFAULT_LARGE_ICON = PDPlugin
.getDefault().getImageDescriptor(
"palette/GENERIC/large/PD_Palette_Default.gif");
// how many characters to truncate a palette item's description to.
// TODO: add preference?
// the soft length is the ideal length we try to truncate to. We first
// try to find a period (end of sentence; TODO: should have a character class)
// inside the first SOFT_LENGTH chars at which to truncate a description string.
// if we can't find one then we search for the first one between SOFT_LENGTH
// and min(HARD_LENGTH, str.length()). If found, we truncate there. If not,
// we truncate to HARD_LENGTH-" ...".length() and append the ellipsis.
// In all cases the truncated description string returned should <= HARD_LENGTH.
// private final static int DESCRIPTION_TRUNCATE_SOFT_LENGTH = 150;
private final static int DESCRIPTION_TRUNCATE_HARD_LENGTH = 250;
/**
* Creates a TaglibPaletteDrawer with TagTool palette entries for each tag from the CMDocument
* @param manager
* @param project
* @param doc
* @return TaglibPaletteDrawer
*/
public static TaglibPaletteDrawer configPaletteItemsByTLD(IPaletteItemManager manager, IProject project,
CMDocument doc) {
//bit of a hack... could be greatly improved
String tldURI = null;
if (doc instanceof TLDDocument){
tldURI = ((TLDDocument)doc).getUri();
}
else if (doc instanceof HTMLCMDocument){
tldURI = CMDocType.HTML_DOC_TYPE;
}
else if (doc instanceof JSPCMDocument){
tldURI = CMDocType.JSP11_DOC_TYPE;
}
if (tldURI == null)
return null;
TaglibPaletteDrawer category = findCategory(manager, tldURI);
if (category != null)
return category;
IMetaDataModelContext modelContext = MetaDataQueryHelper.createTagLibraryDomainMetaDataModelContext(project, tldURI);
Model model = MetaDataQueryHelper.getModel(modelContext);
category = createTaglibPaletteDrawer(manager, doc, model);
if (category != null){
loadTags(category, doc, model);
sortTags(category.getChildren());
}
return category;
}
private static void sortTags(List tags) {
//note that once we store ordering customizations, we will need to do something different
//it will also be complicated if we decide to do 181958 and 181866
Collections.sort(tags, new Comparator(){
public int compare(Object o1, Object o2) {
String label1 = ((PaletteEntry)o1).getLabel();
String label2 = ((PaletteEntry)o2).getLabel();
return label1.compareTo(label2);
}
});
}
private static void loadTags(TaglibPaletteDrawer category,
CMDocument doc,Model model) {
if (model != null) {//load from metadata - should always drop in here
Trait trait = MetaDataQueryHelper.getTrait(model, "paletteInfos");
if (trait != null){
PaletteInfos tags = (PaletteInfos)trait.getValue();
for (Iterator it=tags.getInfos().iterator();it.hasNext();){
PaletteInfo tag = (PaletteInfo)it.next();
createTagEntry(category, tag);
}
} else {
for (Iterator it=model.getChildEntities().iterator();it.hasNext();){
Entity tagAsEntity = (Entity)it.next();
createTagEntry(category, tagAsEntity);
}
}
}
else {//fail safe loading from cmDoc... should no longer go in here
loadFromCMDocument(category, doc);
}
}
private static TaglibPaletteDrawer createTaglibPaletteDrawer(IPaletteItemManager manager,
CMDocument doc, Model model) {
TaglibPaletteDrawer category = null;
if (model != null){
//do we create it?
boolean isHidden = getBooleanTagTraitValue(model, "hidden", false);
if (isHidden){
return null;
}
String label = getStringTagTraitValue(model, "display-label", model.getId());
label = label.equals("") ? model.getId() : label;
category = manager.createTaglibPaletteDrawer(model.getId(), label);
String desc = getStringTagTraitValue(model, "description", model.getId());
category.setDescription(formatDescription(desc));
ImageDescriptor largeIconImage = getImageDescriptorFromTagTraitValueAsString(model, "small-icon", null);
if (largeIconImage != null)
category.setLargeIcon(largeIconImage);
String prefix = getStringTagTraitValue(model, "default-prefix", null);
category.setDefaultPrefix(prefix);
boolean isVisible = !(getBooleanTagTraitValue(model, "expert", false));
category.setVisible(isVisible);
category.setInitialState(PaletteDrawer.INITIAL_STATE_CLOSED);
}
return category;
}
private static TaglibPaletteDrawer findCategory(IPaletteItemManager manager,
String tldURI) {
TaglibPaletteDrawer lib = null;
for (Iterator it = manager.getAllCategories().iterator();it.hasNext();){
lib = (TaglibPaletteDrawer)it.next();
if (tldURI.equals(lib.getURI()))
return lib;
}
return null;
}
/* (non-JavaDoc)
* This method will read information from the CMDocument to create the tag entries. It will
* check the existing items in the registry. If the corresponding tag is not
* in palette manager, then it will create one, and mark the newly created
* item as "expert". Otherwise, it will check whether the tld contains more
* information than the palette manager, and adding those information to it
* (such as description, icons for tags)
*
* @param category
* @param cmdoc
*/
private static void loadFromCMDocument(TaglibPaletteDrawer category,
CMDocument cmdoc) {
CMNamedNodeMap nodeMap = cmdoc.getElements();
for (int i = 0, size = nodeMap.getLength(); i < size; i++) {
CMElementDeclaration eledecl = (CMElementDeclaration) nodeMap
.item(i);
String tagName = eledecl.getElementName();
TagToolPaletteEntry item;
if (tagName.equalsIgnoreCase(IHTMLConstants.TAG_INPUT)) {//TODO: fix this nonsense!
StringBuffer name = new StringBuffer(category.getURI());
name.append(":").append(tagName).append(":").append(tagName);
item = category.getTagPaletteEntryById(name.toString());
} else {
item = category.getTagPaletteEntryByTagName(tagName);
}
if (item == null) {
createTagEntry(category, eledecl);
}
}
}
private static void createTagEntry(TaglibPaletteDrawer category,
PaletteInfo info) {
Boolean hidden = info.getHidden();
if ((hidden != null) && (hidden.booleanValue()))//do not create a palette entry
return;
IMetaDataSourceModelProvider sourceProvider = ((Trait)info.eContainer().eContainer()).getSourceModelProvider();
String tagName = info.getTag();
String id = info.getId();
String label = info.getDisplayLabel();
String desc = formatDescription(info.getDescription());
ImageDescriptor smallIcon = getImageDescriptorFromString(sourceProvider, info.getSmallIcon(), DEFAULT_SMALL_ICON);
ImageDescriptor largeIcon = getImageDescriptorFromString(sourceProvider, info.getLargeIcon(), DEFAULT_LARGE_ICON);
Boolean expert = info.getExpert();
internalCreateTagEntry(category, id, tagName, label, desc, smallIcon, largeIcon, (expert !=null && expert.booleanValue()));
}
private static void createTagEntry(TaglibPaletteDrawer category,
Entity entity) {
boolean hidden = getBooleanTagTraitValue(entity, "hidden", false);
if (hidden)//do not create a palette entry
return;
String tagName = entity.getId();
String label = getStringTagTraitValue(entity, "display-label", tagName);
String desc = formatDescription(getStringTagTraitValue(entity, "description", tagName));
ImageDescriptor smallIcon = getImageDescriptorFromTagTraitValueAsString(entity, "small-icon", DEFAULT_SMALL_ICON);
ImageDescriptor largeIcon = getImageDescriptorFromTagTraitValueAsString(entity, "large-icon", DEFAULT_LARGE_ICON);
boolean expert = getBooleanTagTraitValue(entity, "expert", false);
internalCreateTagEntry(category, tagName, tagName, label, desc, smallIcon, largeIcon, expert);
}
private static TagToolPaletteEntry internalCreateTagEntry(TaglibPaletteDrawer category, String id, String tagName, String label, String desc, ImageDescriptor smallIcon, ImageDescriptor largeIcon, boolean expert){
TagToolPaletteEntry item = new TagToolPaletteEntry(tagName, label, desc, smallIcon, largeIcon);
item.setId(id);
item.setVisible(!expert);
category.getChildren().add(item);
item.setParent(category);
return item;
}
private static boolean getBooleanTagTraitValue(Entity entity,
String key, boolean defaultValue) {
Trait trait = MetaDataQueryHelper.getTrait(entity, key);
if (trait != null){
return TraitValueHelper.getValueAsBoolean(trait);
}
return defaultValue;
}
private static String getStringTagTraitValue(Entity entity, String key, String defaultValue){
Trait trait = MetaDataQueryHelper.getTrait(entity, key);
if (trait != null){
return TraitValueHelper.getValueAsString(trait);
}
return defaultValue;
}
private static ImageDescriptor getImageDescriptorFromTagTraitValueAsString(Entity entity, String key, ImageDescriptor defaultValue){
Trait t = MetaDataQueryHelper.getTrait(entity, key);
if (t != null){
String imgDesc = TraitValueHelper.getValueAsString(t);
return getImageDescriptorFromString(t.getSourceModelProvider(), imgDesc, defaultValue);
}
return defaultValue;
}
private static ImageDescriptor getImageDescriptorFromString(IMetaDataSourceModelProvider sourceModelProvider, String imgDesc, ImageDescriptor defaultValue){
ImageDescriptor image = defaultValue;
IImageDescriptorProvider imageProvider = (IImageDescriptorProvider)sourceModelProvider.getAdapter(IImageDescriptorProvider.class);
if (imageProvider != null){
image = imageProvider.getImageDescriptor(imgDesc);
}
return image;
}
private static void createTagEntry(TaglibPaletteDrawer category,
CMElementDeclaration eledecl) {
String tagName = eledecl.getElementName();
String label = null;
String desc = null;
if (eledecl instanceof TLDElementDeclaration){
TLDElementDeclaration tag = (TLDElementDeclaration)eledecl;
label = tag.getDisplayName();
desc = tag.getDescription();
}
if (label == null || label.equals(""))
label = tagName;
if (desc == null )
desc = "";
else
desc = formatDescription(desc);
TagToolPaletteEntry item = internalCreateTagEntry(category, tagName, tagName, label, desc, getDefaultSmallIcon(), getDefaultLargeIcon(), false);
item.setToolProperty("CMElementDeclaration", eledecl);
}
/**
* @return DEFAULT_LARGE_ICON
*/
private static ImageDescriptor getDefaultLargeIcon() {
return DEFAULT_LARGE_ICON;
}
/**
* @return DEFAULT_SMALL_ICON
*/
private static ImageDescriptor getDefaultSmallIcon() {
return DEFAULT_SMALL_ICON;
}
private static String formatDescription(final String desc) {
//TODO: modify and use a formatter in the future?
String aDesc = filterConvertString(desc);
if (aDesc != null){
if (aDesc.length() > DESCRIPTION_TRUNCATE_HARD_LENGTH) {
StringBuffer result = new StringBuffer(aDesc.substring(0, DESCRIPTION_TRUNCATE_HARD_LENGTH));
result.append("...");
return result.toString();
}
return aDesc;
}
return "";
}
private static String filterConvertString(String text) {
if (text == null) {
return "";
}
String result = removeHTMLTags.matcher(text).replaceAll("");
result = removeNewLines.matcher(result).replaceAll(" ");
result = trimInteriorWhitespace.matcher(result).replaceAll(" ");
return result;
}
}