/*******************************************************************************
* Copyright (c) 2007 Cambridge Semantics Incorporated.
* 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
*
* File: $Source$
* Created by: Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
* Created on: Sep 18, 2007
* Revision: $Id$
*
* Contributors:
* Cambridge Semantics Incorporated - initial API and implementation
*******************************************************************************/
package org.openanzo.jet.exceptions;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* PropertiesDefintionParser handles the parsed results of a properties definition file.
*
* @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
*
*/
public class PropertiesDefinitionParser extends DefaultHandler {
/** The current char buffer for the current element being processed */
StringBuffer currentChars = null;
static final String propertiesGroup = "propertiesGroup";
static final String property = "property";
static final String example = "example";
static final String description = "description";
static final String tag = "tag";
PropertyGroup currentGroup = null;
Property currentProperty = null;
Description currentDescription = null;
Example currentExample = null;
Tag currentTag = null;
ArrayList<PropertyGroup> groups = new ArrayList<PropertyGroup>();
/**
* Capitalize the first Letter of a string, and the first letter following a .
*
* @param value
* @return new string where first Letter of the string is capitalized, as well the any letter following a .
*/
public static String capFirstLetter(String value) {
String newString = value.substring(0, 1).toUpperCase() + value.substring(1, value.length());
if (newString.contains(".")) {
newString = newString.substring(0, newString.indexOf('.')) + capFirstLetter(newString.substring(newString.indexOf('.') + 1));
}
return newString;
}
/**
* Replace all '.', and capitalize the letters following the '.'s.
*
* @param value
* @return new string where any letter following a '.' is capitalized.
*/
public static String replaceDots(String value) {
String newString = value;
if (newString.contains(".")) {
newString = newString.substring(0, newString.indexOf('.')) + capFirstLetter(newString.substring(newString.indexOf('.') + 1));
}
return newString;
}
/**
* Get the PropertyGroup for this parser
*
* @return the PropertyGroup for this parser
*/
public PropertyGroup getGroup() {
return currentGroup;
}
/** Class representing a Property */
public class Property {
String name;
String key;
PropType type;
String defaultValue;
boolean isRestartRequired = true;
boolean quoteDefault = true;
boolean passDefault = false;
String parentProperty = null;
ArrayList<Description> generalDescription;
Description clientDescription;
Description serverDescription;
Description embeddedDescription;
ArrayList<Tag> tags = new ArrayList<Tag>();
ArrayList<Example> generalExample;
Example clientExample;
Example serverExample;
Example embeddedExample;
String minValue;
String maxValue;
/**
* Determine if this property has a description
*
* @return true if this property has a description
*/
public boolean hasDescription() {
return generalDescription != null || clientDescription != null || serverDescription != null || embeddedDescription != null;
}
/**
* Determine if this property has an example
*
* @return true if this property has an example
*/
public boolean hasExample() {
return generalExample != null || clientExample != null || serverExample != null || embeddedExample != null;
}
/**
* Get the name of this property
*
* @return the name of this property
*/
public String getName() {
return name;
}
/**
* Get the key string for this property
*
* @return the key string for this property
*/
public String getKey() {
return key;
}
/**
* Get the property value type
*
* @return the property value type
*/
public PropType getType() {
return type;
}
/**
* Get the default value for this property
*
* @return the default value for this property
*/
public String getDefaultValue() {
return defaultValue;
}
/**
* Should get method take a default value as a parameter
*
* @return if method should take a default value as a parameter
*/
public boolean getPassDefault() {
return passDefault;
}
/**
* Get the general description for this property
*
* @return the general description for this property
*/
public ArrayList<Description> getGeneralDescription() {
return generalDescription;
}
/**
* Return special description information when this property is being used in client mode
*
* @return special description information when this property is being used in client mode
*/
public Description getClientDescription() {
return clientDescription;
}
/**
* Return special description information when this property is being used in server mode
*
* @return special description information when this property is being used in server mode
*/
public Description getServerDescription() {
return serverDescription;
}
/**
* Return special description information when this property is being used in embedded mode
*
* @return special description information when this property is being used in embedded mode
*/
public Description getEmbeddedDescription() {
return embeddedDescription;
}
/**
* Return example information for this property
*
* @return example information for this property
*/
public ArrayList<Example> getGeneralExample() {
return generalExample;
}
/**
* Return special example information when this property is being used in client mode
*
* @return special example information when this property is being used in client mode
*/
public Example getClientExample() {
return clientExample;
}
/**
* Return special example information when this property is being used in server mode
*
* @return special example information when this property is being used in server mode
*/
public Example getServerExample() {
return serverExample;
}
/**
* Return special example information when this property is being used in embedded mode
*
* @return special example information when this property is being used in embedded mode
*/
public Example getEmbeddedExample() {
return embeddedExample;
}
/**
* Return if quote characters should be placed around the default value string
*
* @return true if quote characters should be placed around the default value string
*/
public boolean getQuoteDefault() {
return quoteDefault;
}
/**
* Return any special tags for this property like @see
*
* @return any special tags for this property like @see
*/
public ArrayList<Tag> getTags() {
return tags;
}
/**
* Return the minimum value constraint on this property
*
* @return the minimum value constraint on this property
*/
public String getMinValue() {
return minValue;
}
/**
* Return the maximum value constraint on this property
*
* @return the maximum value constraint on this property
*/
public String getMaxValue() {
return maxValue;
}
/**
* Fallback property to check if property not present
*
* @return fallback property to check if property not present
*/
public String getParentProperty() {
return parentProperty;
}
/**
* Fallback property to check if property not present
*
* @return fallback property to check if property not present, with last . replaced with #
*/
public String getParentPropertyLink() {
if (parentProperty != null) {
int lastIndex = parentProperty.lastIndexOf('.');
if (lastIndex > -1) {
return parentProperty.substring(0, lastIndex).concat("#").concat(parentProperty.substring(lastIndex + 1));
}
}
return null;
}
/**
* Set fallback property to check if property not present
*
* @param parentProperty
* Fallback property to check if property not present
*/
public void setParentProperty(String parentProperty) {
this.parentProperty = parentProperty;
}
/**
* @return the isRestartRequired
*/
public boolean isRestartRequired() {
return isRestartRequired;
}
/**
* @param isRestartRequired
* the isRestartRequired to set
*/
public void setRestartRequired(boolean isRestartRequired) {
this.isRestartRequired = isRestartRequired;
}
}
/**
* Class representing a group of properties that get combined into a class
*/
public class PropertyGroup {
String name;
String packageName;
/**
* @param packageName
* the packageName to set
*/
public void setPackageName(String packageName) {
this.packageName = packageName;
}
String prefix;
ArrayList<Tag> tags = new ArrayList<Tag>();
Description description;
ArrayList<Property> properties = new ArrayList<Property>();
/**
* Get the class name that all the properties in this group are a member
*
* @return the class name that all the properties in this group are a member
*/
public String getClassName() {
return name;
}
/**
* Get the package name for the class
*
* @return the package name for the class
*/
public String getPackageName() {
return packageName;
}
/**
* Get the prefix for the property keys
*
* @return the prefix for the property keys
*/
public String getPrefix() {
return prefix;
}
/**
* Get the description of the class
*
* @return the description of the class
*/
public Description getDescription() {
return description;
}
/**
* Get the set of properties for this class
*
* @return the set of properties for this class
*/
public ArrayList<Property> getProperties() {
return properties;
}
/**
* Get any special tags for this class
*
* @return any special tags for this class
*/
public ArrayList<Tag> getTags() {
return tags;
}
}
/**
* Representation of a description value
*/
public class Description {
String value;
Type type;
/**
* Get the value of the description
*
* @return the value of the description
*/
public String getValue() {
return value;
}
/**
* Get the type of description
*
* @return the type of description
*/
public Type getType() {
return type;
}
}
/**
* Representation of a tag value
*/
public class Tag {
String value;
String type;
/**
* Get the value of the tag
*
* @return the value of the tag
*/
public String getValue() {
return value;
}
/**
* Get the type of tag
*
* @return the type of tag
*/
public String getType() {
return type;
}
}
/**
* Representation of an Example
*/
public class Example {
String value;
Type type;
/**
* Get the value of the example
*
* @return the value of the example
*/
public String getValue() {
return value;
}
/**
* Get the type of the example
*
* @return the type of the example
*/
public Type getType() {
return type;
}
}
/**
* Types of examples and descriptions
*/
public enum Type {
/** Client example or description */
CLIENT,
/** Server example or description */
SERVER,
/** Embedded example or description */
EMBEDDED,
/** General example or description */
GENERAL
}
/**
* Types of property values
*/
public enum PropType {
/** String property value */
STRING,
/** Boolean property value */
BOOLEAN,
/** Long property value */
LONG,
/** Integer property value */
INTEGER,
/** ENCRYPTED string property value */
ENCRYPTED
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
super.startElement(uri, localName, name, attributes);
if (propertiesGroup.equals(name)) {
currentGroup = new PropertyGroup();
currentGroup.packageName = attributes.getValue("packageName");
currentGroup.prefix = attributes.getValue("groupPrefix");
currentGroup.name = attributes.getValue("className");
groups.add(currentGroup);
} else if (tag.equals(name)) {
currentTag = new Tag();
currentTag.type = attributes.getValue("type");
currentChars = new StringBuffer();
} else if (property.equals(name)) {
currentProperty = new Property();
currentProperty.name = attributes.getValue("name");
currentProperty.key = attributes.getValue("key");
currentProperty.parentProperty = attributes.getValue("parentProperty");
currentProperty.passDefault = Boolean.parseBoolean(attributes.getValue("passDefault"));
currentProperty.quoteDefault = Boolean.parseBoolean(attributes.getValue("quoteDefault"));
currentProperty.defaultValue = attributes.getValue("defaultValue");
currentProperty.minValue = attributes.getValue("min");
currentProperty.maxValue = attributes.getValue("max");
String type = attributes.getValue("type");
if (type != null) {
if ("String".equals(type)) {
currentProperty.type = PropType.STRING;
} else if ("Encrypted".equals(type)) {
currentProperty.type = PropType.ENCRYPTED;
} else if ("Long".equals(type)) {
currentProperty.type = PropType.LONG;
} else if ("Integer".equals(type)) {
currentProperty.type = PropType.INTEGER;
} else if ("Boolean".equals(type)) {
currentProperty.type = PropType.BOOLEAN;
}
}
String rr = attributes.getValue("restartRequired");
if (rr != null) {
currentProperty.isRestartRequired = Boolean.parseBoolean(rr);
}
currentGroup.properties.add(currentProperty);
} else if (example.equals(name)) {
currentExample = new Example();
String type = attributes.getValue("type");
if (type == null) {
type = "";
}
if ("Client".equals(type)) {
currentExample.type = Type.CLIENT;
currentProperty.clientExample = currentExample;
} else if ("Server".equals(type)) {
currentExample.type = Type.SERVER;
currentProperty.serverExample = currentExample;
} else if ("Embedded".equals(type)) {
currentExample.type = Type.EMBEDDED;
currentProperty.embeddedExample = currentExample;
} else {
currentExample.type = Type.GENERAL;
if (currentProperty.generalExample == null) {
currentProperty.generalExample = new ArrayList<Example>();
}
currentProperty.generalExample.add(currentExample);
}
currentChars = new StringBuffer();
} else if (description.equals(name)) {
currentDescription = new Description();
String type = attributes.getValue("type");
if (type == null) {
type = "";
}
if ("Client".equals(type)) {
currentDescription.type = Type.CLIENT;
if (currentProperty != null) {
currentProperty.clientDescription = currentDescription;
}
} else if ("Server".equals(type)) {
currentDescription.type = Type.SERVER;
if (currentProperty != null) {
currentProperty.serverDescription = currentDescription;
}
} else if ("Embedded".equals(type)) {
currentDescription.type = Type.EMBEDDED;
if (currentProperty != null) {
currentProperty.embeddedDescription = currentDescription;
}
} else {
currentDescription.type = Type.GENERAL;
if (currentProperty != null) {
if (currentProperty.generalDescription == null) {
currentProperty.generalDescription = new ArrayList<Description>();
}
currentProperty.generalDescription.add(currentDescription);
} else {
currentGroup.description = currentDescription;
}
}
currentChars = new StringBuffer();
}
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
super.endElement(uri, localName, name);
if (example.equals(name)) {
currentExample.value = currentChars.toString();
} else if (description.equals(name)) {
currentDescription.value = currentChars.toString();
} else if (property.equals(name)) {
currentProperty = null;
} else if (tag.equals(name)) {
currentTag.value = currentChars.toString();
if (currentProperty != null) {
currentProperty.tags.add(currentTag);
} else {
currentGroup.tags.add(currentTag);
}
}
currentChars = null;
}
@Override
public void characters(char[] ch, int start, int length) {
if (currentChars != null) {
currentChars.append(ch, start, length);
}
}
/**
* Get the set of property groups that were parsed
*
* @return the set of property groups that were parsed
*/
public ArrayList<PropertyGroup> getGroups() {
return groups;
}
}