// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/tools/symbology/milStd2525/CodeScheme.java,v $
// $RCSfile: CodeScheme.java,v $
// $Revision: 1.9 $
// $Date: 2004/10/14 18:06:29 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.tools.symbology.milStd2525;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import com.bbn.openmap.util.ComponentFactory;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;
/**
* The CodeScheme represents the options presented in the first
* character of the 15 character symbol code. This character
* represents the scheme, or symbology set, of the top-most branches
* of the MIL-STD-2525B symbol tree. The layout and meaning of the 15
* characters depend on the scheme, and the CodeScheme can figure out
* some of them when it parses the position properties to see what
* other CodePositions are fundamental for a particular instance of a
* CodeScheme. There are other CodePositions that present choices for
* a particular scheme type, and the CodeScheme needs to be told what
* those options are. The CodePositionTree handles setting up the
* CodeScheme with its optional CodePositions.
*/
public class CodeScheme extends CodePosition {
/**
* The base 15 character code for a symbol under a scheme. This
* code has wild-cards and unused charaters in them where
* appropriate for the scheme.
*/
protected String defaultSymbolCode = SymbolPart.DEFAULT_SYMBOL_CODE;
/**
* For parsing the hierarchy, most schemes have some characters
* added to their hierarchy index number. This can be specified in
* the position properties.
*/
protected String hierarchyAddition;
/**
* Property keyword for the default symbol code
* 'defaultSymbolCode'.
*/
public final static String DefaultSymbolCodeProperty = "defaultSymbolCode";
/**
* Property keyword for the hierarchy addition string
* 'hierarchyCodeAddition'.
*/
public final static String HierarchyCodeAdditionProperty = "hierarchyCodeAddition";
public CodeScheme() {
super("Scheme", 1, 1);
}
/**
* The method needs more information from the properties than the
* CodePosition version of this method provides, like getting the
* base symbol code for the scheme and the hierarchy addition.
*/
public CodePosition addPositionChoice(int index, String entry,
String prefix, Properties props) {
CodeScheme cs = (CodeScheme) super.addPositionChoice(index,
entry,
prefix,
props);
prefix = PropUtils.getScopedPropertyPrefix(prefix) + entry + ".";
String next = props.getProperty(prefix + NextProperty);
if (next != null) {
String nextClassName = props.getProperty(next + ".class");
if (nextClassName != null) {
CodePosition cp = (CodePosition) ComponentFactory.create(nextClassName);
if (DEBUG) {
Debug.output("CodeScheme created next class(" + next
+ "), " + nextClassName);
}
if (cp != null) {
cs.nextPosition = cp;
cp.parsePositions(next, props);
}
} else {
if (DEBUG) {
Debug.output("CodeScheme couldn't create next class("
+ next + "), " + nextClassName);
}
}
}
cs.defaultSymbolCode = props.getProperty(prefix
+ DefaultSymbolCodeProperty);
cs.hierarchyAddition = props.getProperty(prefix
+ HierarchyCodeAdditionProperty, "");
// Don't need to add to choices, already done in super class
// method.
return cs;
}
/**
* Parse the hierarchy properties to create SymbolParts for those
* parts under a particular scheme represented by this instance of
* CodeScheme.
*
* @param props the hierarchy properties.
* @param parent the SymbolPart parent that the new SymbolPart
* tree falls under.
*/
public SymbolPart parseHierarchy(Properties props, SymbolPart parent) {
String hCode = getHierarchyNumber() + hierarchyAddition;
String entry = props.getProperty(hCode);
SymbolPart sp = null;
if (entry != null) {
sp = new SymbolPart(this, entry, props, parent);
parseHierarchy(hCode, props, sp);
}
return sp;
}
/**
* Parse the hierarchy properties to create SymbolParts for those
* parts under a particular scheme represented by this instance of
* CodeScheme.
*
* @param hCode the hierarchy code of this scheme, used to grow
* the tree for subsequent generations.
* @param props the hierarchy properties.
* @param parent the SymbolPart parent that the new SymbolPart
* tree falls under.
*/
public void parseHierarchy(String hCode, Properties props, SymbolPart parent) {
List codePositionList = null;
if (nextPosition != null) {
codePositionList = nextPosition.getPositionChoices();
}
if (codePositionList == null || codePositionList.isEmpty()) {
Debug.output(prettyName
+ ".parseHierarchy(): codePositionList.size = 0");
return;
}
List parentList = null;
for (Iterator it = codePositionList.iterator(); it.hasNext();) {
CodePosition cp = (CodePosition) it.next();
String newHCode = hCode + "." + cp.getHierarchyNumber();
if (DEBUG) {
Debug.output("CodeScheme.parse: " + newHCode + " with "
+ cp.getPrettyName());
}
String entry = props.getProperty(newHCode);
if (entry != null) {
SymbolPart sp = new SymbolPart(cp, entry, props, parent);
if (parentList == null) {
parentList = parent.getSubs();
if (parentList == null) {
parentList = new ArrayList();
parent.setSubs(parentList);
}
}
if (DEBUG) {
Debug.output("CodeScheme.parse: adding "
+ sp.getPrettyName() + " to "
+ parent.getPrettyName());
}
parentList.add(sp);
if (DEBUG) {
Debug.output("CodeScheme.parse: handling "
+ cp.getPrettyName() + " children for "
+ sp.getPrettyName());
}
cp.parseHierarchy(newHCode, props, sp);
} else {
if (DEBUG) {
Debug.output("CodeScheme.parse: no entry found for "
+ newHCode);
}
}
}
}
/**
* Return the default 15 character symbol code for this instance
* of a scheme. Pretty much all of the symbols below this node in
* the SymbolPart tree will have the same base code, with their
* parameters written on top of it.
*/
public StringBuffer getDefaultSymbolCode() {
return new StringBuffer(defaultSymbolCode);
}
/**
* A set of CodePostitions that can be set with on this scheme.
* It's different from the choices, which is a list of
* instantiated CodePositions for a particular CodePosition. The
* options are a set of CodePositions, containing choices. For
* instance, for a warfighing code scheme, there would be code
* positions for affiliation, status, order of battle and
* modifiers. The metoc code scheme wouldn't have options. Each
* CodePosition returned in the options can represent a setting
* for the position (its choices will be null), or can represent a
* suite of choices if there is a list of other CodePositions in
* its choices parameter.
*/
protected CodeOptions options;
/**
* Set the code options for this scheme.
*/
public void setCodeOptions(CodeOptions co) {
options = co;
}
/**
* Get the code options set for this scheme.
*/
public CodeOptions getCodeOptions() {
return options;
}
/**
* Get the code options for the scheme as it relates to the symbol
* part. The symbol part may have some restrictions set on it by
* having one of the option CodePositions set within it. If that's
* the case, then the CodeOptions returned will have the
* CodePosition object for that aspect of the symbol represented
* by a CodePosition object without choices.
*/
public CodeOptions getCodeOptions(SymbolPart sp) {
// Check with the symbol part first to see of there are any
// options for the particular positions established and
// limiting for the particular symbol, and then substitute
// defaults for any other positions.
return options;
}
}