simplenlg.framework.DocumentElement Maven / Gradle / Ivy
/*
* The contents of this file are subject to the Mozilla Public License
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* https://www.mozilla.org/en-US/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is "Simplenlg".
*
* The Initial Developer of the Original Code is Ehud Reiter, Albert Gatt and Dave Westwater.
* Portions created by Ehud Reiter, Albert Gatt and Dave Westwater are Copyright (C) 2010-11 The University of Aberdeen. All Rights Reserved.
*
* Contributor(s): Ehud Reiter, Albert Gatt, Dave Westwater, Roman Kutlak, Margaret Mitchell, and Saad Mahamood.
*/
package simplenlg.framework;
import java.util.ArrayList;
import java.util.List;
/**
*
* DocumentElement
is a convenient extension of the base
* NLGElement
class. It used to define elements that form part of
* the textual structure (documents, sections, paragraphs, sentences, lists). It
* essentially operates as the base class with the addition of some convenience
* methods for getting and setting features specific to this type of element.
*
*
* TextElements
can be structured in a tree-like structure where
* elements can contain child components. These child components can in turn
* contain other child components and so on. There are restrictions on the type
* of child components a particular element type can have. These are explained
* under the DocumentCategory
enumeration.
*
* Instances of this class can be created through the static create methods in
* the OrthographyProcessor
.
*
*
* @author D. Westwater, University of Aberdeen.
* @version 4.0
*/
public class DocumentElement extends NLGElement {
/**
* The feature relating to the title or heading of this element.
*/
private static final String FEATURE_TITLE = "textTitle"; //$NON-NLS-1$
/**
* The feature relating to the components (or child nodes) of this element.
*/
private static final String FEATURE_COMPONENTS = "textComponents"; //$NON-NLS-1$
/**
* The blank constructor. Using this constructor will require manual setting
* of the element's category and title.
*/
public DocumentElement() {
// Do nothing
}
/**
* Creates a new DocumentElement with the given category and title.
*
* @param category the category for this element.
* @param textTitle the title of this element, predominantly used with DOCUMENT
* and SECTION types.
*/
public DocumentElement(DocumentCategory category, String textTitle) {
this.setCategory(category);
setTitle(textTitle);
}
/**
* Sets the title of this element. Titles are specifically used with
* documents (the document name) and sections (headings).
*
* @param textTitle the new title for this element.
*/
public void setTitle(String textTitle) {
this.setFeature(FEATURE_TITLE, textTitle);
}
/**
* Retrieves the title of this element.
*
* @return the title of this element as a string.
*/
public String getTitle() {
return this.getFeatureAsString(FEATURE_TITLE);
}
/**
* Retrieves the child components of this element.
*
* @return a List
of NLGElement
s representing the
* child components.
*/
public List getComponents() {
return this.getFeatureAsElementList(FEATURE_COMPONENTS);
}
/**
*
* Add a single child component to the current list of child components. If
* there are no existing child components a new list is created.
*
*
* Note that there are restrictions on which child types can be added to
* which parent types. Intermediate nodes are added if necessary; eg,
* if a sentence is added to a document, the sentence will be embedded
* in a paragraph before it is added
* See
* DocumentCategory
for further information.
*
*
* @param element the NLGElement
to be added. If this is
* NULL
the method does nothing.
*/
public void addComponent(NLGElement element) {
if(element != null) {
ElementCategory thisCategory = this.getCategory();
ElementCategory category = element.getCategory();
if(category != null && thisCategory instanceof DocumentCategory) {
if(((DocumentCategory) thisCategory).hasSubPart(category)) {
addElementToComponents(element);
} else {
NLGElement promotedElement = promote(element);
if(promotedElement != null)
addElementToComponents(promotedElement);
else // error condition - add original element so something is visible
addElementToComponents(element);
}
} else {
addElementToComponents(element);
}
}
}
/**
* add an element to a components list
*/
private void addElementToComponents(NLGElement element) {
List components = getComponents();
components.add(element);
element.setParent(this);
setComponents(components);
}
/**
* promote an NLGElement so that it is at the right level to be added to a DocumentElement/
* Promotion means adding surrounding nodes at higher doc levels
*/
private NLGElement promote(NLGElement element) {
// check if promotion needed
if(((DocumentCategory) this.getCategory()).hasSubPart(element.getCategory())) {
return element;
}
// if element is not a DocumentElement, embed it in a sentence and recurse
if(!(element instanceof DocumentElement)) {
DocumentElement sentence = new DocumentElement(DocumentCategory.SENTENCE, null);
sentence.addElementToComponents(element);
return promote(sentence);
}
// if element is a Sentence, promote it to a paragraph
if(element.getCategory() == DocumentCategory.SENTENCE) {
DocumentElement paragraph = new DocumentElement(DocumentCategory.PARAGRAPH, null);
paragraph.addElementToComponents(element);
return promote(paragraph);
}
// otherwise can't do anything
return null;
}
/**
*
* Adds a collection of NLGElements
to the list of child
* components. If there are no existing child components, then a new list is
* created.
*
*
* As with addComponents(...)
only legitimate child types are
* added to the list.
*
*
* @param textComponents the List
of NLGElement
s to be added.
* If this is NULL
the method does nothing.
*/
public void addComponents(List> textComponents) {
if(textComponents != null) {
ElementCategory thisCategory = this.getCategory();
ArrayList elementsToAdd = new ArrayList();
ElementCategory category = null;
for(Object eachElement : textComponents) {
if(eachElement instanceof NLGElement) {
category = ((NLGElement) eachElement).getCategory();
if(category != null && thisCategory instanceof DocumentCategory) {
if(((DocumentCategory) thisCategory).hasSubPart(category)) {
elementsToAdd.add((NLGElement) eachElement);
((NLGElement) eachElement).setParent(this);
}
}
}
}
if(elementsToAdd.size() > 0) {
List components = getComponents();
if(components == null) {
components = new ArrayList();
}
components.addAll(elementsToAdd);
this.setFeature(FEATURE_COMPONENTS, components);
}
}
}
/**
* Removes the specified component from the list of child components.
*
* @param textComponent the component to be removed.
* @return true
if the element was removed, or
* false
if the element did not exist, there is no
* component list or the the given component to remove is
* NULL
.
*/
public boolean removeComponent(NLGElement textComponent) {
boolean removed = false;
if(textComponent != null) {
List components = getComponents();
if(components != null) {
removed = components.remove(textComponent);
}
}
return removed;
}
/**
* Removes all the child components from this element.
*/
public void clearComponents() {
List components = getComponents();
if(components != null) {
components.clear();
}
}
/**
* Child elements of a DocumentElement
are the components. This
* method is the same as calling getComponents()
.
*/
@Override
public List getChildren() {
return getComponents();
}
/**
* Replaces the existing components with the supplied list of components.
* This is identical to calling:
*
* clearComponents();
* addComponents(components);
*
*/
public void setComponents(List components) {
this.setFeature(FEATURE_COMPONENTS, components);
}
@Override
public String printTree(String indent) {
String thisIndent = indent == null ? " |-" : indent + " |-"; //$NON-NLS-1$ //$NON-NLS-2$
String childIndent = indent == null ? " | " : indent + " | "; //$NON-NLS-1$ //$NON-NLS-2$
String lastIndent = indent == null ? " \\-" : indent + " \\-"; //$NON-NLS-1$ //$NON-NLS-2$
String lastChildIndent = indent == null ? " " : indent + " "; //$NON-NLS-1$ //$NON-NLS-2$
StringBuffer print = new StringBuffer();
print.append("DocumentElement: category=").append( //$NON-NLS-1$
getCategory().toString());
String realisation = getRealisation();
if(realisation != null) {
print.append(" realisation=").append(realisation); //$NON-NLS-1$
}
print.append('\n');
List children = getChildren();
int length = children.size() - 1;
int index = 0;
if(children.size() > 0) {
for(index = 0; index < length; index++) {
print.append(thisIndent).append(children.get(index).printTree(childIndent));
}
print.append(lastIndent).append(children.get(index).printTree(lastChildIndent));
}
return print.toString();
}
}