toxgene.core.genes.trees.ToxElement Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ToxGene Show documentation
Show all versions of ToxGene Show documentation
Modified ToXGene for the iBench project.
The newest version!
/**
* Provides an inteface to the basic building block of XML documents (the
* elements).
*
* @author Denilson Barbosa
* @version 0.1 */
package toxgene.core.genes.trees;
import java.io.PrintStream;
import java.util.Vector;
import toxgene.core.Engine;
import toxgene.core.ToXgeneErrorException;
import toxgene.core.genes.*;
import toxgene.core.genes.lists.ListGene;
import toxgene.core.genes.lists.ToxList;
import toxgene.core.genes.lists.ToxListElement;
import toxgene.core.genes.lists.ToxListElementException;
import toxgene.core.genes.literals.LiteralGene;
import toxgene.core.parser.ToxComplexType;
import toxgene.core.random.ToxRandom;
public class ToxElement implements TreeGene, ListGene {
/**
* Tag name for the element.
*/
private String tagname;
/**
* Minimum and maximun numbers of occurrences for actual instances
*/
private int min_qtty, max_qtty;
/**
* determines whether this element has a predefined upper limit on its
* number of occurrences (i.e., max_qtty).
*/
private boolean get_max_qtty = false;
/**
* Pseudo-random number generator
*/
private ToxRandom randomGenerator;
/**
* Vector with all direct attributes of the element.
*/
private Vector attributes;
/**
* Vector for the genes that define the contents of the element,
* regardless of its content model.
*/
private Vector contents;
/**
* Vector with all container objects inside this element. Container
* objects contain attributes and other elements that might or might not
* be generated, depending on factors external to this element.
*/
private Vector containers;
/**
* Vector with all genes that have variable number of occurrences. These
* genes determine the actual number of occurrences of the current
* element. Each element in this vector is also in the contents vector
* (inserted in the correct order of appearence in the input template) and
* is generated like any other gene.
*/
private Vector varQttyContents;
/**
* Vector with all tox-scan elements that are direct children of this
* elment, used to reset them before generating any data. Each element in
* this vector is also in the varQttyContents (thus also in the contents)
* vector.
*/
private Vector scans;
/**
* Determines whether this element is a literal or a tree gene.
*/
private boolean isLiteral;
/**
* Determines whether this gene's contents have to be reset each time the
* gene is instantiated.
*/
private boolean resetGenes;
/**
* Determines whether this element is the recursive ancestor of another.
* If not, the element is "memoryless"
*/
private boolean isRecursiveAncestor;
/**
* Number of times the gene will be instantiated.
*/
private int times;
/**
* Number of times the gene was already instantiaded.
*/
private int instance;
/**
* ToXgene engine...
*/
private Engine tgEngine;
public ToxElement() {
//do nothing. Defined so that ToxRecursiveMixedContent will compile
}
public ToxElement(String tagname, int min_qtty, int max_qtty,
ToxRandom randomGenerator,boolean isLiteral,
boolean resetGenes, boolean isRecursiveAncestor,
Engine engine) {
this.tagname = tagname;
this.min_qtty = min_qtty;
this.max_qtty = max_qtty;
this.times = 0;
this.instance = 0;
this.isRecursiveAncestor = isRecursiveAncestor;
tgEngine = engine;
get_max_qtty = (max_qtty == -1);
contents = new Vector();
attributes = new Vector();
containers = new Vector();
varQttyContents = new Vector();
scans = new Vector();
this.randomGenerator = randomGenerator;
this.isLiteral = isLiteral;
this.resetGenes = resetGenes;
}
/**
* returns the number of instances left -- used by the recursive
* descendat to know how many instances to generate.
*/
public int getQttyLeft() {
return times - instance;
}
/**
* determines how many instances of this gene will be produced
*/
public int getQtty() {
int times = min_qtty, max = max_qtty;
if (get_max_qtty) {
int qtty = 0;
for (int k = 0; k < varQttyContents.size(); k++) {
qtty = ((VarQttyGene) varQttyContents.get(k)).getMaxQtty();
if ((max == -1) || (qtty < max)) {
max = qtty;
}
}
if (max < min_qtty) {
throw new ToXgeneErrorException(
"cannot generate minimun quantity of "
+ "\""
+ tagname
+ "\" element.");
}
times = max;
}
if (max_qtty != -1) {
//in this case the template specifies actual min and max qtties
if (min_qtty != max) {
times = (int) randomGenerator.nextInt(max);
}
}
return times;
}
/**
* Generates one single instance of the gene for being added to the given
* list.
*/
public ToxListElement instance(ToxList list) {
int tagNumber = tgEngine.getTagNumber(tagname);
ToxListElement child = new ToxListElement(tagNumber);
if (resetGenes) {
reset();
}
try {
for (int j = 0; j < contents.size(); j++) {
//output all the subelements for this element
((ListGene) contents.get(j)).generate(child);
}
} catch (NoElementsException e) {
throw new ToXgeneErrorException(
"cannot generate more instances of element: " + tagname);
}
return child;
}
/**
* Notifies all scan genes that the output of this gene failed uniqueness
* or where clause constraints.
*/
public void failed() {
int size = scans.size();
if (size > 0) {
for (int i = 0; i < scans.size(); i++) {
((ToxScan) scans.get(i)).rollback();
}
} else {
for (int i = 0; i < contents.size(); i++) {
if (((Gene) contents.get(i)) instanceof ToxElement) {
((ToxElement) contents.get(i)).failed();
}
}
}
}
/**
* Resets the gene.
*/
public void reset() {
for (int i = 0; i < attributes.size(); i++) {
((Gene) attributes.get(i)).reset();
}
for (int i = 0; i < contents.size(); i++) {
((Gene) contents.get(i)).reset();
}
}
/**
* Adds the output of the gene as children of the give ToxListElement.
*/
public void generate(ToxListElement parent) {
if (resetGenes) {
reset();
}
//determines the actual number of occurrences for this element
times = getQtty();
try {
//resets all scan objects
for (int i = 0; i < scans.size(); i++) {
((ToxScan) scans.get(i)).update();
}
for (instance = 0; instance < times; instance++) {
int tagNumber = tgEngine.getTagNumber(tagname);
ToxListElement child = parent.addChild(tagNumber);
//no attributes in lists :)
for (int j = 0; j < contents.size(); j++) {
//output all the subelements for this element
((ListGene) contents.get(j)).generate(child);
}
}
} catch (NoElementsException e) {
throw new ToXgeneErrorException(
"cannot generate more instances of element: " + tagname);
}
}
/**
* Outputs the actual contents of this element into the outStream.
*/
public void generate(PrintStream outStream){
if (resetGenes) {
reset();
}
//determines the actual number of occurrences for this element
times = getQtty();
//resets all scan objects
for (int i = 0; i < scans.size(); i++) {
((ToxScan) scans.get(i)).update();
}
if (isRecursiveAncestor) {
//in this case, we need to keep track of the number of instances.
//and, each time a recursive child is generated, we must count
while (instance < times) {
instance++;
try {
//output the tagname for the object
outStream.print("<" + tagname);
for (int j = 0; j < attributes.size(); j++) {
//ouput all attributes for the element
((Gene) attributes.get(j)).generate(outStream);
}
for (int j = 0; j < containers.size(); j++) {
//ouput all attributes for the element residing in child container
((ContainerGene) containers.get(j)).generateAttributes(
outStream);
}
outStream.print(">"); //done with attributes
for (int j = 0; j < contents.size(); j++) {
//output all the subelements for this element
((Gene) contents.get(j)).generate(outStream);
}
outStream.print("" + tagname + ">");
} catch (NoElementsException e) {
throw new ToXgeneErrorException(
"cannot generate more instances of element: "
+ tagname);
}
if (tgEngine.addNewLines()) {
outStream.print("\n");
}
}
instance = 0;
} else {
//isRecursiveAncestor==false here. then, we go on "memoryless mode"
try {
for (instance = 0; instance < times; instance++) {
//output the tagname for the object
outStream.print("<" + tagname);
for (int j = 0; j < attributes.size(); j++) {
//ouput all attributes for the element
((Gene) attributes.get(j)).generate(outStream);
}
for (int j = 0; j < containers.size(); j++) {
//ouput all attributes for the element residing in child container
((ContainerGene) containers.get(j)).generateAttributes(
outStream);
}
outStream.print(">"); //done with attributes
for (int j = 0; j < contents.size(); j++) {
//output all the subelements for this element
((Gene) contents.get(j)).generate(outStream);
}
outStream.print("" + tagname + ">");
if (tgEngine.addNewLines()) {
outStream.print("\n");
}
}
} catch (NoElementsException e) {
throw new ToXgeneErrorException(
"cannot generate more instances of element: " + tagname);
}
}
}
/**
* Outputs the actual contents of this element into the outStream. This
* version is used only for recursive elements
*/
public void generateRecursive(PrintStream outStream, int depth) {
if (instance < times) {
instance++;
//resets all scan objects
for (int i = 0; i < scans.size(); i++) {
((ToxScan) scans.get(i)).update();
}
try {
outStream.print("<" + tagname);
for (int j = 0; j < attributes.size(); j++) {
//ouput all attributes for the element
((Gene) attributes.get(j)).generate(outStream);
}
for (int j = 0; j < containers.size(); j++) {
//ouput all attributes for the element residing in child container
//no recursive attribute generation yet!!!
((ContainerGene) containers.get(j)).generateAttributes(
outStream);
}
outStream.print(">"); //done with attributes
for (int j = 0; j < contents.size(); j++) {
Gene gene = (Gene) contents.get(j);
if (gene instanceof ToxAlternatives) {
((ToxAlternatives) gene).generateRecursive(
outStream,
depth);
} else {
if (gene instanceof ToxScan) {
((ToxScan) gene).generateRecursive(
outStream,
depth);
} else {
gene.generate(outStream);
}
}
}
} catch (NoElementsException e) {
throw new ToXgeneErrorException(
"cannot generate more instances of element: " + tagname);
}
outStream.print("" + tagname + ">");
}
}
/**
* Outputs the actual contents of this element into the outStream. This
* version is used only for recursive elements
*/
public void generateRecursive(ToxListElement element, int depth) {
if (instance < times) {
instance++;
//resets all scan objects
for (int i = 0; i < scans.size(); i++) {
((ToxScan) scans.get(i)).update();
}
try {
int tagNumber = tgEngine.getTagNumber(tagname);
ToxListElement child = new ToxListElement(tagNumber);
//no attributes in lists :)
for (int j = 0; j < contents.size(); j++) {
//output all the subelements for this element
ListGene gene = (ListGene) contents.get(j);
if (gene instanceof ToxAlternatives) {
((ToxAlternatives) gene).generateRecursive(
child,
depth);
} else {
gene.generate(child);
}
}
} catch (NoElementsException e) {
throw new ToXgeneErrorException(
"cannot generate more instances of element: " + tagname);
}
}
}
public void addAttribute(ToxAttribute attr) {
attributes.add(attr);
}
public void addContent(Gene item) {
contents.add(item);
}
public void addComplexType(ToxComplexType holder) {
attributes.addAll(holder.attributes());
contents.addAll(holder.contents());
containers.addAll(holder.containers());
varQttyContents.addAll(holder.varQttyContents());
scans.addAll(holder.scans());
}
/**
* Adds a new attribute container to this element.
*/
public void addContainer(ContainerGene gene) {
get_max_qtty = true;
containers.add(gene);
}
/**
* Adds a new gene to the contents of the element. This gene has a
* variable number of occurrences, depending on the result of a
* query. This number of occurrences is used to compute the actual number
* of occurrences for this element. The child gene is also added to the
* content list for this element.
*/
public void addVarQttyContent(VarQttyGene gene) {
varQttyContents.add(gene);
contents.add(gene);
}
/**
* Adds a new tox-scan/tox-sample gene to the list of scan genes in this
* element. This gene is also added to the contents vector so that it is
* processed in the correct order.
*/
public void addScan(ToxScan gene) {
scans.add(gene);
addVarQttyContent(gene);
}
/**
* Outputs the tagName for the element. Used for a ToxFile element when
* printing the doctype information.
*/
public String tagName() {
return tagname;
}
public String name() {
return tagname;
}
public Vector children() {
return contents;
}
public Vector getChildren() {
Vector result = null;
for (int i = 0; i < contents.size(); i++) {
ListGene gene = (ListGene) contents.get(i);
if (gene instanceof LiteralGene) {
continue;
}
if (gene instanceof ToxScan
|| gene instanceof ToxAlternatives
|| gene instanceof ToxIf) {
Vector children = gene.getChildren();
if (children != null) {
if (result == null) {
result = new Vector();
}
result.addAll(children);
}
continue;
}
if (result == null) {
result = new Vector();
}
result.add(gene);
}
return result;
}
public Vector getChildrenByName(String name)
throws ToxListElementException {
if (contents.size() == 0) {
throw new ToxListElementException();
}
Vector result = null;
for (int i = 0; i < contents.size(); i++) {
ListGene gene = (ListGene) contents.get(i);
if (gene instanceof LiteralGene) {
continue;
}
if (gene instanceof ToxScan
|| gene instanceof ToxAlternatives
|| gene instanceof ToxIf) {
Vector children = gene.getChildrenByName(name);
if (children != null) {
if (result == null) {
result = new Vector();
}
result.addAll(children);
}
continue;
}
if (name.compareTo(gene.name()) == 0) {
if (result == null) {
result = new Vector();
}
result.add(gene);
}
}
return result;
}
public int numIterators() {
int result = 0;
for (int i = 0; i < contents.size(); i++) {
result += ((Gene) contents.get(i)).numIterators();
}
for (int i = 0; i < attributes.size(); i++) {
result += ((Gene) attributes.get(i)).numIterators();
}
return result;
}
public void destroy() {
try {
for (int i = 0; i < contents.size(); i++) {
((Gene) contents.get(i)).destroy();
}
for (int i = 0; i < attributes.size(); i++) {
((Gene) attributes.get(i)).destroy();
}
contents.clear();
attributes.clear();
containers.clear();
varQttyContents.clear();
scans.clear();
contents = null;
attributes = null;
containers = null;
varQttyContents = null;
scans = null;
} catch (Exception e) {
}
}
/**
* Returns the datatype of instances of this gene.
*/
public String getType() {
int size = contents.size();
String result = null;
for (int i = 0; i < size; i++) {
ListGene gene = (ListGene) contents.get(i);
if (gene instanceof ToxElement) {
return "complex";
}
if (gene instanceof LiteralGene) {
result = reconcile(result, gene.getType());
}
if (gene instanceof ToxScan
|| gene instanceof ToxIf
|| gene instanceof ToxAlternatives) {
Vector children = gene.getChildren();
int size2 = children == null ? 0 : children.size();
for (int j = 0; j < size; j++) {
ListGene child = (ListGene) children.get(j);
if (child instanceof ToxElement) {
return "complex";
} else {
String subtype = child.getType();
result = reconcile(result, subtype);
}
}
}
}
return result;
}
private String reconcile(String t1, String t2) {
if (t1 == null) {
return t2;
}
if (t2 == null) {
return t1;
}
if (t1.compareTo(t2) == 0) {
return t1;
}
if (t1.compareTo("string") == 0 || t2.compareTo("string") == 0) {
return "string";
}
if (t1.compareTo("complex") == 0 || t2.compareTo("complex") == 0) {
return "complex";
}
if ((t1.compareTo("integer") == 0 && t2.compareTo("real") == 0)
|| (t2.compareTo("integer") == 0 && t1.compareTo("real") == 0)) {
return "real";
}
if ((t1.compareTo("integer") == 0 && t2.compareTo("date") == 0)
|| (t2.compareTo("integer") == 0 && t1.compareTo("date") == 0)) {
return "date";
}
return "complex";
}
}