/*
* -----------------------------------------------------------------------
* File: $HeadURL$
* Revision $LastChangedRevision$
* Last Modified: $LastChangedDate$
* Last Change by: $LastChangedBy$
* -----------------------------------------------------------------------
* Copyright (C) 2007 Keith Stribley <devel@thanlwinsoft.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
* -----------------------------------------------------------------------
*/
/**
*
*/
package org.thanlwinsoft.languagetest.language.test.meta;
import java.util.ArrayDeque;
import java.util.Comparator;
import java.util.TreeSet;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.thanlwinsoft.languagetest.eclipse.workspace.WorkspaceLanguageManager;
import org.thanlwinsoft.schemas.languagetest.module.ConfigType;
import org.thanlwinsoft.schemas.languagetest.module.DescType;
import org.thanlwinsoft.schemas.languagetest.module.LangType;
import org.thanlwinsoft.schemas.languagetest.module.MetaDataType;
import org.thanlwinsoft.schemas.languagetest.module.TagType;
import org.thanlwinsoft.schemas.languagetest.module.TestItemType;
/**
* @author keith
* Class to wrap MetaData nodes
*/
public class MetaNode
{
public static final String SEPARATOR = "/";
private MetaNode parent = null;
private MetaDataType data = null;
private MetaNode() {}
public MetaNode(MetaNode parent, MetaDataType data)
{
this.parent = parent;
this.data = data;
}
public MetaNode getParent()
{
return parent;
}
public boolean isOrphan() { return (parent == null); }
public boolean hasChildren() { return data.sizeOfMetaDataArray() > 0; }
public MetaNode [] getChildren()
{
MetaNode [] nodes = new MetaNode[data.sizeOfMetaDataArray()];
for (int i = 0; i < data.sizeOfMetaDataArray(); i++)
{
nodes[i] = new MetaNode(this, data.getMetaDataArray(i));
}
return nodes;
}
public void addMetaData(MetaDataType newChild)
{
for (MetaDataType md : data.getMetaDataArray())
{
if (md.getMetaId().equals(newChild.getMetaId()))
{
MetaNode mn = new MetaNode(this, md);
for (MetaDataType mdChild : newChild.getMetaDataArray())
{
mn.addMetaData(mdChild);
}
break;
}
}
data.addNewMetaData().set(newChild.copy());
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (obj == null) return false;
if (obj instanceof MetaNode)
{
MetaNode mn = (MetaNode)obj;
if (mn.data.getMetaId().equals(data.getMetaId())) return true;
}
else if (obj.toString().equals(data.getMetaId()))
{
return true;
}
return false;
}
public IPath toPath()
{
IPath p = null;
if (parent == null)
p = new Path(data.getMetaId());
else
{
p = parent.toPath().append(data.getMetaId());
}
return p;
}
public String getString()
{
return data.getMetaId();
}
public String getPath()
{
return getPath(getDefaultLang());
}
public String getPath(String lang)
{
if (parent == null)
{
return SEPARATOR + getName(lang);
}
else
{
return parent.getPath(lang) + SEPARATOR + getName(lang);
}
}
public String getName(String lang)
{
String name = data.getMetaId();
for (int i = 0; i < data.sizeOfDescArray(); i++)
{
DescType desc = data.getDescArray(i);
if (desc.getLang().equals(lang))
{
name = desc.getStringValue();
return name;
}
// if the prefix is the same, then its probably a good substitute
int langLength = Math.min(lang.length(), desc.getLang().length());
if (desc.getLang().startsWith(lang.substring(0, langLength)))
{
name = desc.getStringValue();
}
}
return name;
}
public String getName()
{
return getName(getDefaultLang());
}
protected String getDefaultLang()
{
String lang = System.getProperty("osgi.nl");
LangType [] userLangs = WorkspaceLanguageManager.findUserLanguages();
if (userLangs != null && userLangs.length > 0)
lang = userLangs[0].getLang();
if (lang == null)
lang = "en";
return lang;
}
protected ArrayDeque<MetaNode> getNodeAxis()
{
ArrayDeque<MetaNode> nodeAxis = new ArrayDeque<MetaNode>();
nodeAxis.push(this);
MetaNode top = this;
while (top.parent != null)
{
top = top.parent;
nodeAxis.push(top);
}
return nodeAxis;
}
public boolean isSetOnItem(TestItemType item)
{
String ref = toPath().toPortableString();
for (int i = 0; i < item.sizeOfTagArray(); i++)
{
TagType tag = item.getTagArray(i);
if (tag.getRef().equals(ref))
{
return true;
}
}
return false;
}
public void setOnItem(TestItemType item, boolean state)
{
if (item == null) // may be null when used in search dialog
return;
String ref = toPath().toPortableString();
for (int i = 0; i < item.sizeOfTagArray(); i++)
{
TagType tag = item.getTagArray(i);
if (tag.getRef().equals(ref))
{
if (state) return; // already set
else
{
item.removeTag(i);
return;
}
}
}
item.addNewTag().setRef(ref);
}
public static MetaNode [] getTopLevelNodes(ConfigType config)
{
MetaNode[] nodes = new MetaNode[config.sizeOfMetaDataArray()];
for (int i = 0; i < config.sizeOfMetaDataArray(); i++)
{
MetaDataType md = config.getMetaDataArray(i);
nodes[i] = new MetaNode(null, md);
}
return nodes;
}
/**
* Get the top level meta data nodes as an array from the Config nodes.
* @param config
* @return
*/
public static MetaNode [] getTopLevelNodes(ConfigType [] config)
{
Comparator <MetaNode> comparator = new MetaNode().new LeafComparator();
TreeSet <MetaNode> nodes = new TreeSet<MetaNode>(comparator);
for (int i = 0; i < config.length; i++)
{
if (config[i] != null)
{
MetaNode[] configNodes = getTopLevelNodes(config[i]);
for (int j = 0; j < configNodes.length; j++)
{
if (nodes.contains(configNodes[j]))
{
MetaNode masterNode = nodes.subSet(configNodes[j],
true, configNodes[j], true).first();
for (MetaNode mn : configNodes[j].getChildren())
{
masterNode.addMetaData(mn.data);
}
}
else
{
nodes.add(configNodes[j]);
}
}
}
}
return nodes.toArray(new MetaNode[nodes.size()]);
}
/**
* Compare MetaNodes at the same level in a tree.
* @author keith
* Note: this comparator comparator imposes orderings that are inconsistent
* with MetaNode.equals()."
* @param <MetaNode>
*/
class LeafComparator implements Comparator<MetaNode>
{
MetaNode mn;
public LeafComparator() {};
/* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(MetaNode o1, MetaNode o2)
{
if (o1 == null)
{
if (o2 == null) return 0;
return -1;
}
else if (o2 == null)
{
return 1;
}
// TODO implement a locale comparator based on descriptions
return o1.data.getMetaId().compareTo(o2.data.getMetaId());
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
return (obj instanceof LeafComparator);
}
}
/**
* @return
*/
public String getId()
{
return data.getMetaId();
}
/**
* @return
*/
public MetaDataType getData()
{
return data;
}
}