/*******************************************************************************
* Copyright (c) 2007, 2013 David Green 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:
* David Green - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.wikitext.parser.markup;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Writer;
import java.util.Collections;
import java.util.Set;
import org.eclipse.mylyn.wikitext.parser.DocumentBuilder;
import org.eclipse.mylyn.wikitext.parser.MarkupParser;
import org.eclipse.mylyn.wikitext.util.ServiceLocator;
import com.google.common.collect.ImmutableSet;
/**
* A markup language, which knows its formatting rules and is able to process content based on {@link Block},
* {@link PatternBasedElementProcessor} and {@link PatternBasedElement} concepts. All markup languages supported by
* WikiText extend this class.
* <p>
* The MarkupLanguage class provides basic functionality for determining which blocks process which markup content in a
* particular document. In general multi-line documents are split into consecutive regions called blocks, and each line
* in a block is processed with spanning sections called phrase modifiers, and tokens within a span are replaced with
* their respective replacement tokens. These rules apply to most lightweight markup languages, however subclasses may
* override this default functionality if required. For example, by default phrase modifiers are non-overlapping and
* non-nested, however if required a subclass could permit such nesting.
* </p>
* <p>
* Generally markup language classes are not accessed directly by client code, instead client code should configure and
* call {@link MarkupParser}, accessing the markup language by name using the {@link ServiceLocator}.
* </p>
*
* @author David Green
* @since 3.0
*/
public abstract class MarkupLanguage implements Cloneable {
private static final DefaultIdGenerationStrategy DEFAULT_ID_GENERATION_STRATEGY = new DefaultIdGenerationStrategy();
private String name;
private String extendsLanguage;
private Set<String> fileExtensions;
@Override
public MarkupLanguage clone() {
MarkupLanguage markupLanguage;
try {
markupLanguage = getClass().newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
markupLanguage.setName(name);
markupLanguage.setExtendsLanguage(extendsLanguage);
return markupLanguage;
}
/**
* get the id strategy employed by this markup language.
*/
public IdGenerationStrategy getIdGenerationStrategy() {
return DEFAULT_ID_GENERATION_STRATEGY;
}
/**
* configure the markup language with a configuration that may alter the language syntax and capabilities.
*
* @param configuration
* the configuration to use
* @throws UnsupportedOperationException
* markup languages that do not support configuration must throw this exception.
*/
public void configure(MarkupLanguageConfiguration configuration) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* The name of the markup language, typically the same as the name of the markup language supported by this markup
* language. This value may be displayed to the user.
*
* @return the name, or null if unknown
*/
public String getName() {
return name;
}
/**
* The name of the markup language, typically the same as the name of the markup language supported by this markup
* language. This value may be displayed to the user.
*
* @param name
* the name
*/
public void setName(String name) {
this.name = name;
}
/**
* Provides the normal file extensions of this markup language. The default implementation returns a set of
* {@link #getName()}.
*
* @return the file extensions
*/
public Set<String> getFileExtensions() {
if (fileExtensions == null) {
return Collections.singleton(getName());
}
return fileExtensions;
}
/**
* Sets the normal file extensions of this markup language.
*
* @return the file extensions
* @see #getFileExtensions()
*/
public void setFileExtensions(Set<String> fileExtensions) {
checkNotNull(fileExtensions, "Must specify file extensions"); //$NON-NLS-1$
checkArgument(!fileExtensions.isEmpty(), "File extensions must not be empty"); //$NON-NLS-1$
this.fileExtensions = ImmutableSet.copyOf(fileExtensions);
}
/**
* The name of the markup language that is extended by this one
*
* @return the name, or null if this markup language does not extend another.
*/
public String getExtendsLanguage() {
return extendsLanguage;
}
/**
* The name of the markup language that is extended by this one
*
* @param extendsLanguage
* the name, or null if this markup language does not extend another.
*/
public void setExtendsLanguage(String extendsLanguage) {
this.extendsLanguage = extendsLanguage;
}
public abstract void processContent(MarkupParser parser, String markupContent, boolean asDocument);
/**
* Creates a {@link DocumentBuilder} suitable for emitting content in this markup language. Equivalent to
* {@code createDocumentBuilder(out,false)}.
*
* @param out
* the target to which content is written
* @return a document builder
* @throws UnsupportedOperationException
* if the markup language has no corresponding document builder
* @see #createDocumentBuilder(Writer, boolean)
*/
public DocumentBuilder createDocumentBuilder(Writer out) {
return createDocumentBuilder(out, false);
}
/**
* Creates a {@link DocumentBuilder} suitable for emitting content in this markup language.
*
* @param out
* the target to which content is written
* @param formatting
* indicates if the builder should format the output using pretty-print rules. If not supported by the
* document builder this parameter is ignored.
* @return a document builder
* @throws UnsupportedOperationException
* if the markup language has no corresponding document builder
*/
public DocumentBuilder createDocumentBuilder(Writer out, boolean formatting) {
throw new UnsupportedOperationException();
}
}