/*=============================================================================#
# Copyright (c) 2014-2016 Stephan Wahlbrink (WalWare.de) 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:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.docmlet.wikitext.internal.ui.sourceediting;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.mylyn.internal.wikitext.ui.WikiTextUiPlugin;
import org.eclipse.mylyn.internal.wikitext.ui.editor.assist.Templates;
import org.eclipse.mylyn.wikitext.core.parser.Attributes;
import org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder;
import org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder.BlockType;
import org.eclipse.mylyn.wikitext.core.parser.MarkupParser;
import org.eclipse.mylyn.wikitext.core.parser.markup.AbstractMarkupLanguage;
import org.eclipse.mylyn.wikitext.core.parser.markup.MarkupLanguage;
import org.eclipse.mylyn.wikitext.ui.WikiText;
import de.walware.ecommons.ltk.IElementName;
import de.walware.ecommons.ltk.core.model.IModelElement;
import de.walware.docmlet.wikitext.core.markup.IMarkupLanguage;
import de.walware.docmlet.wikitext.core.model.IWikitextElement;
import de.walware.docmlet.wikitext.core.model.WikitextModel;
public class MarkupTemplates {
public static class MarkupInfo implements IModelElement {
private final int headingLevel;
private final BlockType blockType;
private final int modelElementType;
public MarkupInfo() {
this.headingLevel= 0;
this.blockType= null;
this.modelElementType= 0;
}
public MarkupInfo(final int headingLevel) {
this.headingLevel= headingLevel;
this.blockType= null;
this.modelElementType= IWikitextElement.C2_SECTIONING | headingLevel;
}
public MarkupInfo(final BlockType blockType) {
this.headingLevel= 0;
this.blockType= blockType;
this.modelElementType= 0;
}
public int getHeadingLevel() {
return this.headingLevel;
}
public BlockType getBlockType() {
return this.blockType;
}
@Override
public String getModelTypeId() {
return WikitextModel.WIKIDOC_TYPE_ID;
}
@Override
public Object getAdapter(final Class adapter) {
return null;
}
@Override
public int getElementType() {
return this.modelElementType;
}
@Override
public IElementName getElementName() {
return null;
}
@Override
public String getId() {
return null;
}
@Override
public boolean exists() {
return false;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public IModelElement getModelParent() {
return null;
}
@Override
public boolean hasModelChildren(final Filter filter) {
return false;
}
@Override
public List<? extends IModelElement> getModelChildren(final Filter filter) {
return Collections.emptyList();
}
}
private static class TemplateTester extends DocumentBuilder {
private static final Pattern VARIABLE_PATTERN= Pattern.compile("(\\$\\{\\w*\\})"); //$NON-NLS-1$
private final MarkupParser parser;
private MarkupInfo found;
public TemplateTester(MarkupLanguage markupLanguage) {
markupLanguage= markupLanguage.clone();
if (markupLanguage instanceof AbstractMarkupLanguage) {
final AbstractMarkupLanguage language= (AbstractMarkupLanguage) markupLanguage;
language.setFilterGenerativeContents(true);
language.setBlocksOnly(true);
}
this.parser= new MarkupParser(markupLanguage, this);
}
public MarkupInfo createInfo(final Template template) {
this.found= null;
String text= template.getPattern();
text= VARIABLE_PATTERN.matcher(text).replaceAll("Abcdefg ");
text+= "Abcdefg \n\n\n";
try {
this.parser.parse(text);
}
catch (final Exception e) {}
if (this.found == null) {
this.found= new MarkupInfo();
}
return this.found;
}
@Override
public void beginDocument() {
}
@Override
public void endDocument() {
}
@Override
public void beginBlock(final BlockType type, final Attributes attributes) {
this.found= new MarkupInfo(type);
throw new RuntimeException();
}
@Override
public void endBlock() {
}
@Override
public void beginSpan(final SpanType type, final Attributes attributes) {
}
@Override
public void endSpan() {
}
@Override
public void beginHeading(final int level, final Attributes attributes) {
this.found= new MarkupInfo(level);
throw new RuntimeException();
}
@Override
public void endHeading() {
}
@Override
public void characters(final String text) {
}
@Override
public void entityReference(final String entity) {
}
@Override
public void image(final Attributes attributes, final String url) {
}
@Override
public void link(final Attributes attributes, final String hrefOrHashName, final String text) {
}
@Override
public void imageLink(final Attributes linkAttributes, final Attributes imageAttributes,
final String href, final String imageUrl) {
}
@Override
public void acronym(final String text, final String definition) {
}
@Override
public void lineBreak() {
}
@Override
public void charactersUnescaped(final String literal) {
}
}
private final IMarkupLanguage markupLanguage;
private final List<Template> templates;
private final Map<Template, MarkupInfo> templateInfos;
public MarkupTemplates(final IMarkupLanguage markupLanguage) {
this.markupLanguage= markupLanguage;
this.templateInfos= new HashMap<>();
this.templates= init();
}
@SuppressWarnings("restriction")
private List<Template> init() {
final Templates mylynTemplates= getMylynTemplates();
if (mylynTemplates == null) {
return Collections.emptyList();
}
final List<Template> list= mylynTemplates.getTemplate();
final TemplateTester tester= new TemplateTester((MarkupLanguage) this.markupLanguage);
for (final Template template : list) {
if (mylynTemplates.isBlock(template)) {
this.templateInfos.put(template, tester.createInfo(template));
}
}
return list;
}
@SuppressWarnings("restriction")
private Templates getMylynTemplates() {
final Map<String, Templates> map= WikiTextUiPlugin.getDefault().getTemplates();
MarkupLanguage language= (MarkupLanguage) this.markupLanguage;
Templates mylynTemplates;
do {
mylynTemplates= map.get(language.getName());
}
while (mylynTemplates == null && language.getExtendsLanguage() != null
&& (language= WikiText.getMarkupLanguage(language.getExtendsLanguage())) != null );
return mylynTemplates;
}
public List<Template> getTemplates() {
return this.templates;
}
public MarkupInfo getMarkupInfo(final Template template) {
return this.templateInfos.get(template);
}
}