* Loads the all the initial BlockGenuses and BlockGenus families of this language
* @param workspace The workspace in use
* @param root the Element carrying the specifications of the BlockGenuses
*/
public static void loadBlockGenera(Workspace workspace, Element root) {
WorkspaceEnvironment env = workspace.getEnv();
Pattern attrExtractor = Pattern.compile("\"(.*)\"");
Matcher nameMatcher;
NodeList genusNodes = root.getElementsByTagName("BlockGenus"); //look for genus
Node genusNode;
StringTokenizer col;
for (int i = 0; i < genusNodes.getLength(); i++) { //find them
genusNode = genusNodes.item(i);
if (genusNode.getNodeName().equals("BlockGenus")) {
/// LOAD BLOCK GENUS PROPERTIES ///
BlockGenus newGenus = new BlockGenus(env);
//first, parse out the attributes
nameMatcher = attrExtractor.matcher(genusNode.getAttributes().getNamedItem("name").toString());
if (nameMatcher.find()) {
newGenus.genusName = nameMatcher.group(1);
}
//assert that no other genus has this name
assert env.getGenusWithName(newGenus.genusName) == null : "Block genus names must be unique. A block genus already exists with this name: " + newGenus.genusName;
nameMatcher = attrExtractor.matcher(genusNode.getAttributes().getNamedItem("color").toString());
if (nameMatcher.find()) { //will be true
col = new StringTokenizer(nameMatcher.group(1));
if (col.countTokens() == 3) {
newGenus.color = new Color(Integer.parseInt(col.nextToken()), Integer.parseInt(col.nextToken()), Integer.parseInt(col.nextToken()));
} else {
newGenus.color = Color.BLACK;
}
}
nameMatcher = attrExtractor.matcher(genusNode.getAttributes().getNamedItem("kind").toString());
if (nameMatcher.find()) {
newGenus.kind = nameMatcher.group(1);
}
nameMatcher = attrExtractor.matcher(genusNode.getAttributes().getNamedItem("initlabel").toString());
if (nameMatcher.find()) {
//implied that it is global, but it may be redefined
newGenus.initLabel = nameMatcher.group(1);
}
nameMatcher = attrExtractor.matcher(genusNode.getAttributes().getNamedItem("editable-label").toString());
if (nameMatcher.find()) {
newGenus.isLabelEditable = nameMatcher.group(1).equals("yes") ? true : false;
}
nameMatcher = attrExtractor.matcher(genusNode.getAttributes().getNamedItem("label-unique").toString());
if (nameMatcher.find()) {
newGenus.labelMustBeUnique = nameMatcher.group(1).equals("yes") ? true : false;
}
//load optional items
Node opt_item = genusNode.getAttributes().getNamedItem("is-starter");
if (opt_item != null) {
nameMatcher = attrExtractor.matcher(opt_item.toString());
if (nameMatcher.find()) {
newGenus.isStarter = nameMatcher.group(1).equals("yes") ? true : false;
}
}
opt_item = genusNode.getAttributes().getNamedItem("is-terminator");
if (opt_item != null) {
nameMatcher = attrExtractor.matcher(opt_item.toString());
if (nameMatcher.find()) {
newGenus.isTerminator = nameMatcher.group(1).equals("yes") ? true : false;
}
}
opt_item = genusNode.getAttributes().getNamedItem("is-label-value");
if (opt_item != null) {
nameMatcher = attrExtractor.matcher(opt_item.toString());
if (nameMatcher.find()) {
newGenus.isLabelValue = nameMatcher.group(1).equals("yes") ? true : false;
}
}
opt_item = genusNode.getAttributes().getNamedItem("label-prefix");
if (opt_item != null) {
nameMatcher = attrExtractor.matcher(opt_item.toString());
if (nameMatcher.find()) {
newGenus.labelPrefix = nameMatcher.group(1);
}
}
opt_item = genusNode.getAttributes().getNamedItem("label-suffix");
if (opt_item != null) {
nameMatcher = attrExtractor.matcher(opt_item.toString());
if (nameMatcher.find()) {
newGenus.labelSuffix = nameMatcher.group(1);
}
}
opt_item = genusNode.getAttributes().getNamedItem("page-label-enabled");
if (opt_item != null) {
nameMatcher = attrExtractor.matcher(opt_item.toString());
if (nameMatcher.find()) {
newGenus.isPageLabelEnabled = nameMatcher.group(1).equals("yes") ? true : false;
}
}
//if genus is a data genus (kind=data) or a variable block (and soon a declaration block)
//it is both a starter and terminator
//in other words, it should not have before and after connectors
if (newGenus.isDataBlock() || newGenus.isVariableDeclBlock() || newGenus.isFunctionBlock()) {
newGenus.isStarter = true;
newGenus.isTerminator = true;
}
//next, parse out the elements
NodeList genusChildren = genusNode.getChildNodes();
Node genusChild;
for (int j = 0; j < genusChildren.getLength(); j++) {
genusChild = genusChildren.item(j);
if (genusChild.getNodeName().equals("description")) {
/// LOAD BLOCK GENUS DESCRIPTION ///
loadGenusDescription(genusChild.getChildNodes(), newGenus);
} else if (genusChild.getNodeName().equals("BlockConnectors")) {
/// LOAD BLOCK CONNECTOR INFORMATION ///
loadBlockConnectorInformation(workspace, genusChild.getChildNodes(), newGenus);
//if genus has two connectors both of bottom position type than this block is an infix operator
if (newGenus.sockets != null && newGenus.sockets.size() == 2
&& newGenus.sockets.get(0).getPositionType() == BlockConnector.PositionType.BOTTOM
&& newGenus.sockets.get(1).getPositionType() == BlockConnector.PositionType.BOTTOM) {
newGenus.isInfix = true;
}
} else if (genusChild.getNodeName().equals("Images")) {
/// LOAD BLOCK IMAGES ///
loadBlockImages(genusChild.getChildNodes(), newGenus);
} else if (genusChild.getNodeName().equals("LangSpecProperties")) {
/// LOAD LANGUAGE SPECIFIC PROPERTIES ///
loadLangDefProperties(genusChild.getChildNodes(), newGenus);
} else if (genusChild.getNodeName().equals("Stubs")) {
/// LOAD STUBS INFO AND GENERATE GENUSES FOR EACH STUB ///
loadStubs(genusChild.getChildNodes(), newGenus);
}
}
// John's code to add command sockets... probably in the wrong place
if (!newGenus.isStarter) {
newGenus.before = new BlockConnector(workspace, BlockConnectorShape.getCommandShapeName(), BlockConnector.PositionType.TOP, "", false, false, Block.NULL);
}
if (!newGenus.isTerminator) {
newGenus.after = new BlockConnector(workspace, BlockConnectorShape.getCommandShapeName(), BlockConnector.PositionType.BOTTOM, "", false, false, Block.NULL);
}
//System.out.println("Added "+newGenus.toString());
env.addBlockGenus(newGenus);
}
}
/////////////////////////////////////
/// LOAD BLOCK FAMILY INFORMATION ///
/////////////////////////////////////
NodeList families = root.getElementsByTagName("BlockFamily");
Node family;
Node member;
String name;
ArrayList<String> famList = new ArrayList<String>();
for (int i = 0; i < families.getLength(); i++) {
family = families.item(i);
for (int j = 0; j < family.getChildNodes().getLength(); j++) {
member = family.getChildNodes().item(j);
if (member.getNodeName().equals("FamilyMember")) { //a family member entry
name = member.getTextContent();
assert env.getGenusWithName(name) != null : "Unknown BlockGenus: " + name;
assert !env.getGenusWithName(name).isLabelEditable : "Genus " + name + " is in a family, but its name is editable";
famList.add(name);
}
}
if (famList.size() > 0) {
for (String memName : famList) {
ArrayList<String> newFamList = new ArrayList<String>(famList);
newFamList.remove(memName); //filter out current memName, so that only
//sibling names are included
env.getGenusWithName(memName).familyList = newFamList;
}
}
famList.clear();
}
}