blob: 4e062894d3fe6efbdbde73de9d7be38bc196abf5 [file] [log] [blame]
/**
* Copyright (c) 2011 Forschungszentrum Juelich GmbH
* 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
*
* Contributors:
* Carsten Karbach, FZ Juelich
*/
package org.eclipse.ptp.rm.lml.internal.core.nodedisplay;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement1;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement2;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement3;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement4;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement5;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement6;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement7;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement8;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement9;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataType;
import org.eclipse.ptp.rm.lml.internal.core.elements.GobjectType;
import org.eclipse.ptp.rm.lml.internal.core.elements.LayoutType;
import org.eclipse.ptp.rm.lml.internal.core.elements.LguiType;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplay;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement0;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement1;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement2;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement3;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement4;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement5;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement6;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement7;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement8;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplayelement9;
import org.eclipse.ptp.rm.lml.internal.core.elements.NodedisplaylayoutType;
import org.eclipse.ptp.rm.lml.internal.core.elements.ObjectsType;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement1;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement2;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement3;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement4;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement5;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement6;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement7;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement8;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement9;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeType;
import org.xml.sax.SAXException;
/**
* This class is a copy of LMLCheck out of a lml-checking-tool
* only function checkImplicitNames is missing
*
* This class supports several view-classes by navigating through the nodedisplays
* @author Carsten Karbach, FZ Juelich
*
*/
public class LMLCheck {
/**
* @return Object of LguiType parsed out of an lml-File
* @throws JAXBException
*/
public static LguiType parseLML(URL xml, URL xsd) throws JAXBException {
//Causes errors while used in applet
JAXBContext jc = JAXBContext.newInstance("lml");
Unmarshaller unmar = jc.createUnmarshaller();
if(xsd!=null){
Schema mySchema;
SchemaFactory sf =
SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
try {
mySchema = sf.newSchema(xsd);
} catch( SAXException saxe ){
// ...(error handling)
mySchema = null;
}
//Connect schema to unmarshaller
unmar.setSchema(mySchema);
}
//Validate lml-file and unmarshall in one step
JAXBElement<LguiType> doc = (JAXBElement<LguiType>) unmar.unmarshal( xml);
//Get root-element
LguiType lml = doc.getValue();
return lml;
}
/**
* get all objects-Tags
* @param model
* @return
*/
public static List<ObjectsType> getObjects(LguiType model) {
List<JAXBElement<?>> all = model.getObjectsAndRelationsAndInformation();
List<ObjectsType> objects = new ArrayList<ObjectsType>();
for (JAXBElement<?> aobj: all) {
if (aobj.getValue() instanceof ObjectsType) {
objects.add((ObjectsType) aobj.getValue());
}
}
return objects;
}
/**
* Get all Layout-Definitions out of the lml-file
* @param pmodell
* @return
*/
public static List<LayoutType> getLayouts(LguiType pmodell) {
List<JAXBElement<?>> all = pmodell.getObjectsAndRelationsAndInformation();
List<LayoutType> layouts = new ArrayList<LayoutType>();
for (JAXBElement<?> aobj: all) {
if (aobj.getValue() instanceof LayoutType) {
layouts.add((LayoutType) aobj.getValue());
}
}
return layouts;
}
/**
* Get all graphical objects out of the lml-file
* @param pmodell
* @return
*/
public static List<GobjectType> getGraphicalObjects(LguiType pmodell) {
List<JAXBElement<?>> all = pmodell.getObjectsAndRelationsAndInformation();
List<GobjectType> gobj = new ArrayList<GobjectType>();
for (JAXBElement<?> aobj: all) {
if (aobj.getValue() instanceof GobjectType) {
gobj.add((GobjectType) aobj.getValue());
}
}
return gobj;
}
/**
* @param el
* @return in which level this dataelement is placed, 0 for DataType, 10 for DataElement (unspecific)
*/
public static int getDataLevel(Object el) {
if (el instanceof DataType) {
return 0;
}
if (el instanceof DataElement1) {
return 1;
}
if (el instanceof DataElement2) {
return 2;
}
if (el instanceof DataElement3) {
return 3;
}
if (el instanceof DataElement4) {
return 4;
}
if (el instanceof DataElement5) {
return 5;
}
if (el instanceof DataElement6) {
return 6;
}
if (el instanceof DataElement7) {
return 7;
}
if (el instanceof DataElement8) {
return 8;
}
if (el instanceof DataElement9) {
return 9;
}
if (el instanceof DataElement) {
return 10;
}
return -1;
}
/**
* Returns a List of lower data-elements for a data-element or a dataType-instance
* within a data-section of a nodedisplay
*
* @param el
* @return
*/
public static List getLowerDataElements(Object el) {
if (el instanceof DataType) {
return ((DataType) el).getEl1();
}
if (el instanceof DataElement1) {
return ((DataElement1)el).getEl2();
}
if (el instanceof DataElement2) {
return ((DataElement2)el).getEl3();
}
if (el instanceof DataElement3) {
return ((DataElement3)el).getEl4();
}
if (el instanceof DataElement4) {
return ((DataElement4)el).getEl5();
}
if (el instanceof DataElement5) {
return ((DataElement5)el).getEl6();
}
if (el instanceof DataElement6) {
return ((DataElement6)el).getEl7();
}
if (el instanceof DataElement7) {
return ((DataElement7)el).getEl8();
}
if (el instanceof DataElement8) {
return ((DataElement8)el).getEl9();
}
if (el instanceof DataElement9) {
return ((DataElement9)el).getEl10();
}
return new ArrayList();
}
/**
* @param el
* @return in which level this schemeelement is placed, 0 for SchemeType, 10 for SchemeElement (unspecific)
*/
public static int getSchemeLevel(Object el){
if (el instanceof SchemeType) {
return 0;
}
if (el instanceof SchemeElement1) {
return 1;
}
if (el instanceof SchemeElement2) {
return 2;
}
if (el instanceof SchemeElement3) {
return 3;
}
if (el instanceof SchemeElement4) {
return 4;
}
if (el instanceof SchemeElement5) {
return 5;
}
if (el instanceof SchemeElement6) {
return 6;
}
if (el instanceof SchemeElement7) {
return 7;
}
if (el instanceof SchemeElement8) {
return 8;
}
if (el instanceof SchemeElement9) {
return 9;
}
if (el instanceof SchemeElement) {
return 10;
}
return -1;
}
/**
* Returns a List of lower scheme elements for a scheme-element or a SchemeType-instance
*
* @param el
* @return
*/
public static List getLowerSchemeElements(Object el) {
if (el instanceof SchemeType) {
return ((SchemeType) el).getEl1();
}
if (el instanceof SchemeElement1) {
return ((SchemeElement1)el).getEl2();
}
if (el instanceof SchemeElement2) {
return ((SchemeElement2)el).getEl3();
}
if (el instanceof SchemeElement3) {
return ((SchemeElement3)el).getEl4();
}
if (el instanceof SchemeElement4) {
return ((SchemeElement4)el).getEl5();
}
if (el instanceof SchemeElement5) {
return ((SchemeElement5)el).getEl6();
}
if (el instanceof SchemeElement6) {
return ((SchemeElement6)el).getEl7();
}
if (el instanceof SchemeElement7) {
return ((SchemeElement7)el).getEl8();
}
if (el instanceof SchemeElement8) {
return ((SchemeElement8)el).getEl9();
}
if (el instanceof SchemeElement9) {
return ((SchemeElement9)el).getEl10();
}
return new ArrayList();
}
/**
* Returns a List of lower nodedisplayelements for a NodedisplayelementX or a NodedisplaylayoutType
*
* @param el
* @return
*/
public static List getLowerNodedisplayElements(Object el) {
if (el instanceof NodedisplaylayoutType) {
ArrayList<Nodedisplayelement0> justonelement = new ArrayList<Nodedisplayelement0>();
justonelement.add( ((NodedisplaylayoutType) el).getEl0() );
return justonelement;
}
if (el instanceof Nodedisplayelement0) {
return ((Nodedisplayelement0)el).getEl1();
}
if (el instanceof Nodedisplayelement1) {
return ((Nodedisplayelement1)el).getEl2();
}
if (el instanceof Nodedisplayelement2) {
return ((Nodedisplayelement2)el).getEl3();
}
if (el instanceof Nodedisplayelement3) {
return ((Nodedisplayelement3)el).getEl4();
}
if (el instanceof Nodedisplayelement4) {
return ((Nodedisplayelement4)el).getEl5();
}
if (el instanceof Nodedisplayelement5) {
return ((Nodedisplayelement5)el).getEl6();
}
if (el instanceof Nodedisplayelement6) {
return ((Nodedisplayelement6)el).getEl7();
}
if (el instanceof Nodedisplayelement7) {
return ((Nodedisplayelement7)el).getEl8();
}
if (el instanceof Nodedisplayelement8) {
return ((Nodedisplayelement8)el).getEl9();
}
if (el instanceof Nodedisplayelement9) {
return ((Nodedisplayelement9)el).getEl10();
}
return new ArrayList();
}
/**
* Returns the height of the scheme-tree given by this schemeEl
* @param schemeEl scheme elements or a SchemeType-instance
* @return
*/
public static int getDeepestSchemeLevel(Object schemeEl) {
if (schemeEl == null) {
return 0;
}
List els = getLowerSchemeElements(schemeEl);
if (els == null) {
return 1;
}
int max = 0;
for (int i = 0; i < els.size(); i++) {
int aheight = getDeepestSchemeLevel(els.get(i));
if (aheight > max) {
max = aheight;
}
}
return max + (schemeEl instanceof SchemeType ? 0: 1);
}
/**
* Parses numberlist (for example 1,2,16,2,100) and returns a list of integers like new int[]{1,2,16,2,100}
* @param numberlist list of numbers separated by commas
* @return integer list
*/
public static int[] getNumbersFromNumberlist(String numberlist) {
String[] parts = numberlist.split(",");
int[] res = new int[parts.length];
int i = 0;
for (String part:parts) {
res[i++] = Integer.parseInt(part.trim());
}
return res;
}
/**
* A class which combines a data-element and the defining scheme-element
* @author karbach
*
*/
public static class SchemeAndData {
public DataElement data;
public SchemeElement scheme;
public SchemeAndData(DataElement pdata, SchemeElement pscheme) {
data = pdata;
scheme = pscheme;
}
}
/**
* Searches within the direct childs of dataEl for a tag
* which includes the idnr number.
*
* @param number number of this element in current level
* @param dataEl data-object of the corresponding nodedisplay or a lower-level data-element
* @return the DataElement in which this scheme-node is described, null if there is no explicitly defined data
*/
public static DataElement isSchemenodeInThisData(int number, Object dataEl) {
List els = getLowerDataElements(dataEl);
if (els == null) {
return null;
}
for (int i = 0; i < els.size(); i++) {
DataElement ael = (DataElement) els.get(i);
if(ael.getMin()!=null){ //ranges
int min = ael.getMin().intValue();
int max = min;
if (ael.getMax() != null) {
max = ael.getMax().intValue();
}
if (number >= min && number <= max) {
return ael;
}
}
else if (ael.getList() != null) {//list-attribute
int[] listels = getNumbersFromNumberlist(ael.getList());//for example 1,2,16,23
for (int anum:listels) {
if (anum == number) {
return ael;
}
}
}
}
return null;
}
/**
* Traverses elements-tree of layout-section for a nodedisplay till all ids given by numbers are found
*
* @param numbers contains level-ids
* @param nodeel upper-level-el-tag
* @return nodedisplayelement describing the object`s layout given by element-ids through numbers
*/
public static Nodedisplayelement getNodedisplayElementByLevels(ArrayList<Integer> numbers, Nodedisplayelement nodeel) {
if (numbers == null || numbers.size() == 0) {
return null;
}
if (nodeel == null) {
return null;
}
int anum = numbers.get(0);
numbers.remove((int)0);//Remove the first element of the arraylist
List schemeEls = getLowerNodedisplayElements(nodeel);
Nodedisplayelement scheme = null;
//Find scheme-tag which contains element with id anum
for (int i = 0; i < schemeEls.size(); i++) {
Nodedisplayelement ascheme = (Nodedisplayelement)schemeEls.get(i);
if (ascheme.getMin() != null) {//Scheme-elements defined by range through min- max-attributes
int amin = ascheme.getMin().intValue();
int amax = amin;
if (ascheme.getMax() != null) {
amax = ascheme.getMax().intValue();
}
if (anum >= amin && anum <= amax) {
scheme = ascheme;
break;
}
}
else if (ascheme.getList() != null) {//Scheme defines list of elements
int[] listels = getNumbersFromNumberlist(ascheme.getList());//for example 1,2,16,23
for (int number:listels) {
if (number == anum) {
scheme = ascheme;
break;
}
}
//if scheme found stop searching
if (scheme != null) {
break;
}
}
}
//No scheme found for anum
if (scheme == null) {
return null;
}
//Real solutions are always found in this part
if (numbers.size() == 0) {
return scheme;//All numbers processed?
}
else{
//are the lower levels of the scheme-node allowed in the data-tag?
Nodedisplayelement res = getNodedisplayElementByLevels(numbers, scheme);
return res;
}
}
/**
* Traverses scheme-tree till all ids given by numbers are found
*
* @param numbers contains level-ids
* @param schemeEl upper-level-scheme-tag
* @return schemeelement describing the object given by element-ids through numbers
*/
public static SchemeElement getSchemeByLevels(ArrayList<Integer> numbers, Object schemeEl) {
if (numbers == null || numbers.size() == 0) {
return null;
}
if (schemeEl == null) {
return null;
}
int anum = numbers.get(0);
numbers.remove((int)0);//Remove the first element of the arraylist
List schemeEls = getLowerSchemeElements(schemeEl);
SchemeElement scheme = null;
//Find scheme-tag which contains element with id anum
for (int i = 0; i < schemeEls.size(); i++) {
SchemeElement ascheme = (SchemeElement)schemeEls.get(i);
if (ascheme.getMin() != null) {//Scheme-elements defined by range through min- max-attributes
int amin = ascheme.getMin().intValue();
int amax = amin;
if (ascheme.getMax() != null) {
amax = ascheme.getMax().intValue();
}
int astep = ascheme.getStep().intValue();
if (anum >= amin && anum <= amax && (anum-amin) % astep == 0 ) {
scheme = ascheme;
break;
}
}
else if (ascheme.getList() != null) {//Scheme defines list of elements
int[] listels = getNumbersFromNumberlist(ascheme.getList());//for example 1,2,16,23
for (int number:listels) {
if (number == anum) {
scheme = ascheme;
break;
}
}
//if scheme found stop searching
if (scheme != null) {
break;
}
}
}
//No scheme found for anum
if (scheme == null) {
return null;
}
//Real solutions are always found in this part
if (numbers.size() == 0) {
return scheme;//All numbers processed?
}
else{
//are the lower levels of the scheme-node allowed in the data-tag?
SchemeElement res = getSchemeByLevels(numbers, scheme);
return res;
}
}
/**
* Nice call for just one number, just creates an arraylist with one number and calls overloaded function
* @param number one integer value with id for the element to be checked
* @param dataEl upper-level data-element
* @param schemeEl scheme-element on the same level as dataEl
* @return Data- and Scheme which are connected to each other
*/
public static SchemeAndData getSchemeAndDataByLevels(int number, Object dataEl, Object schemeEl) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(number);
return getSchemeAndDataByLevels(numbers, dataEl, schemeEl);
}
/**
*
* Searches within the dataEl-tree for a data-element which describes the treenode
* with the level-ids given by numbers.
*
* Returns corresponding scheme-element if available
*
* @param numbers level-ids, which has to be searched in lower elements, content might be changed by this function
* @param dataEl root of the data-tags, which will be processed, dataEl itself is just used to get lower elements
* @param schemeEl root of the scheme-tags, which will be processed, schemeEl itself is just used to get lower elements
* @return data-element and corresponding scheme
*/
public static SchemeAndData getSchemeAndDataByLevels(ArrayList<Integer> numbers, Object dataEl, Object schemeEl) {
// numbers=copyArrayList(numbers);
if (numbers == null || numbers.size() == 0) {
return null;
}
if (schemeEl == null) {
return null;
}
int anum = numbers.get(0);
numbers.remove((int)0);//Remove the first element of the arraylist
List els = getLowerDataElements(dataEl);
List schemeEls = getLowerSchemeElements(schemeEl);
for (int i = 0; i < els.size(); i++) {
DataElement ael = (DataElement) els.get(i);
if (ael.getMin() != null) {//data-Element with ranges
int min = ael.getMin().intValue();
int max = min;
if (ael.getMax() != null) {
max = ael.getMax().intValue();
}
if (min>anum || max < anum) {
continue;
}
//else data-Element for anum found
}
else if (ael.getList() != null) {//check if anum in list
boolean found = false;
int[] listels = getNumbersFromNumberlist(ael.getList());//for example 1,2,16,23
for (int number : listels) {
if (number == anum) {
found = true;
break;
}
}
//if anum not in list, search for another data-element
if (!found) {
continue;
}
}
//Find corresponding scheme-element
SchemeElement scheme = null;
for (int j = 0; j < schemeEls.size(); j++) {
SchemeElement ascheme = (SchemeElement) schemeEls.get(j);
if (ascheme.getMin() != null) {//Scheme-elements defined by range through min- max-attributes
int amin = ascheme.getMin().intValue();
int amax = amin;
if (ascheme.getMax() != null) {
amax = ascheme.getMax().intValue();
}
int astep = ascheme.getStep().intValue();
if (anum >= amin && anum <= amax && (anum-amin) % astep == 0 ) {
scheme = ascheme;
break;
}
}
else if (ascheme.getList() != null) {//Scheme defines list of elements
int[] listels = getNumbersFromNumberlist(ascheme.getList());//for example 1,2,16,23
for (int number : listels) {
if (number == anum) {
scheme = ascheme;
break;
}
}
//if scheme found stop searching
if (scheme != null) {
break;
}
}
}
//No scheme found for the current data-element
if (scheme == null) {
continue;
}
//Real solutions are always found in this part
if (numbers.size() == 0) {
return new SchemeAndData(ael, scheme);//All numbers processed?
}
else{
//are the lower levels of the scheme-node allowed in the data-tag?
SchemeAndData res = getSchemeAndDataByLevels(numbers, ael, scheme);
if (res != null) {
return res;
}
}
}
if(dataEl instanceof DataType){
return null;
}
else
return new SchemeAndData((DataElement) dataEl, (SchemeElement) schemeEl);
}
/**
* @param levels
* @return a string describing the levels of a node within a tree
*/
public static String getLevelString(ArrayList<Integer> levels) {
String levelstring = "";
for (int j = 1; j <= levels.size(); j++) {
levelstring += "el" + j + "=" + levels.get(j-1) + " ";
}
return levelstring;
}
/**
* Copy an Integer-ArrayList
* @param orig
* @return
*/
public static ArrayList<Integer> copyArrayList(ArrayList<Integer> orig) {
ArrayList<Integer> res = new ArrayList<Integer>();
for (int i = 0; i < orig.size(); i++) {
res.add(orig.get(i));
}
return res;
}
/**
* Check if all created data-nodes are allowed as described in the corresponding scheme
* returns list of Errors containing messages about not-allowed nodes in Errorlist
*/
public static void checkDataNodesinScheme(ErrorList errl, Object datanode, ArrayList<Integer> upperlevelnumbers, Object scheme ) {
if (datanode == null) {
return;
}
List els = getLowerDataElements(datanode);
if (els == null) {
return;
}
for (int i = 0; i < els.size(); i++) {
DataElement dat = (DataElement) els.get(i);
if (dat.getMin() != null) {//data-tag given by range => check every element in range
int min = dat.getMin().intValue();
int max = min;
if (dat.getMax() != null) {
max = dat.getMax().intValue();
}
upperlevelnumbers.add(min);
SchemeAndData first = getSchemeAndDataByLevels(min, datanode, scheme);
// SchemeElement first=isDatanodeInScheme(upperlevelnumbers, scheme);
if (first == null) {//Minimum of given data-node is not in scheme
String levelstring = getLevelString(upperlevelnumbers);
errl.addError("\tDatanode with tree-path " + levelstring + " is not allowed in scheme");
}
else{
//Check Lower-Level Data-Nodes
checkDataNodesinScheme(errl, dat, upperlevelnumbers, first.scheme);
int step = first.scheme.getStep().intValue();//default of step is one, even if scheme does not define min- max- attributes
for (int j = min + step; j <= max; j += step) {
upperlevelnumbers.set(upperlevelnumbers.size()-1, j);
//get current schemeanddata
SchemeAndData asad = getSchemeAndDataByLevels(j, datanode, scheme);
// SchemeElement ascheme=isDatanodeInScheme(upperlevelnumbers, scheme);
if (asad == null) {//No scheme found for id j
String levelstring = getLevelString(upperlevelnumbers);
errl.addError("\tDatanode with tree-path " + levelstring + " is not allowed in scheme");
}
else{
//Check inner Nodes
checkDataNodesinScheme(errl, dat, upperlevelnumbers, asad.scheme);
}
}
}
upperlevelnumbers.remove((int)(upperlevelnumbers.size()-1));
} //end of range-checks
else if (dat.getList() != null) {//elements in data-tag defined with a list
upperlevelnumbers.add(0);
int[] elements = getNumbersFromNumberlist(dat.getList());
for (int number : elements) {
upperlevelnumbers.set(upperlevelnumbers.size()-1, number);
SchemeAndData asad = getSchemeAndDataByLevels(number, datanode, scheme);
if (asad == null) {
String levelstring = getLevelString(upperlevelnumbers);
errl.addError("\tDatanode with tree-path " + levelstring + " is not allowed in scheme");
}
else{//current number is allowed, check lower elements
checkDataNodesinScheme(errl, dat, upperlevelnumbers, asad.scheme);
}
}
upperlevelnumbers.remove((int)(upperlevelnumbers.size()-1));
}
}//for-loop over subelements of datanode
}
/**
* @param ids identifying numbers on every level
* @param scheme upper-level scheme object
* @return implicit name for this object by using masks and maps
*/
public static String getImplicitName(ArrayList<Integer> ids, Object scheme) {
if (ids == null || ids.size() == 0 ) {
return "";
}
ArrayList<Integer> id = new ArrayList<Integer>();
id.add(ids.get(0));
SchemeElement subscheme = getSchemeByLevels(copyArrayList(id), scheme);
if (subscheme == null) {
return "";
}
String subname = getLevelName(subscheme, id.get(0));
ids.remove(0);
return subname + getImplicitName(ids, subscheme);
}
/**
* Uses mask-attribute to return formatted output of levelid
* Exception is the definition of map-attribute, then names are explicitly given by map-attribute
* @param scheme corresponding scheme-element
* @param levelid id of the element, the name is searched for
* @return implicit name of the element for this level
*/
public static String getLevelName(SchemeElement scheme, int levelid) {
if (scheme.getMap() == null) {
return String.format(scheme.getMask(), levelid);
}
String[] names = scheme.getMap().split(",");
if (scheme.getMin() != null) {//min-max-attributes
int min = scheme.getMin().intValue();
int max = min;
if (scheme.getMax() != null) {
max = scheme.getMax().intValue();
}
int step = scheme.getStep().intValue();
int namespos = (levelid - min) / step;
if (namespos < names.length) {
return names[namespos];
}
}
else {//List-attribute, map list-ids to map-names, in other words: find position of levelid in list-attribute and return corresponding positioned map-name
int[] nrs = getNumbersFromNumberlist(scheme.getList());
for (int i = 0; i < nrs.length; i++) {
if (nrs[i] == levelid) {
return names[i];
}
}
}
return "";
}
/**
* Searches for allowed implicitly defined names from a name schema.
* Adds all names of elements, which are directly children of the schemeElement.
* Then calls this method again for all children.
*
* @param errlist list of errors occuring while parsing
* @param names allowed names
* @param schemeElement actual node in scheme-tree
* @param aname name of this element, can be extended by the names of children
*/
public static void addAllowedNames(ErrorList errlist, HashSet<String> names, Object schemeElement, String aname) {
List els = getLowerSchemeElements(schemeElement);
if (els == null) {
return;//no sub-elements found
}
for (int i = 0; i < els.size(); i++) {
SchemeElement el = (SchemeElement) els.get(i);
if (el.getMin() != null) {//Lower elements through ranges
int min = el.getMin().intValue();
int max = min;
if (el.getMax() != null) {
max = el.getMax().intValue();
}
int step = el.getStep().intValue();
if (min > max) {
errlist.addError("A min-value is bigger then the appropriate max-value." + aname + " min= " + min + " max= " + max);
}
for (int j = min; j <= max; j += step) {
String thisname = aname + getLevelName(el, j);
names.add(thisname);
addAllowedNames(errlist, names, el, thisname);
}
}
else if (el.getList() != null) {//Lower elements through list
int[] numbers = getNumbersFromNumberlist(el.getList());
for (int number : numbers) {
String thisname = aname+getLevelName(el, number);
names.add(thisname);
addAllowedNames(errlist, names, el, thisname);
}
}
}
}
/**
* Traverses the data-tag-tree and searches for refid-Attributes.
* Then checks whether these attributes have allowed values according to
* name scheme of the corresponding nodedisplay.
* Allowed names are passed as a set of names
*
* Traverses all nodedisplay-references
*
* @param errlist
* @param names
* @param schemeElement
*/
public static void checkNamesAllowed(ErrorList errlist, HashSet<String> names, Object datarefelement) {
List els = getLowerDataElements(datarefelement);
if (els == null) {
return;//Keine Unterelemente gefunden
}
for (int i = 0; i < els.size(); i++) {
DataElement el = (DataElement)els.get(i);
String refname = el.getRefid();
if (refname != null) {
if (!names.contains(refname)) {
errlist.addError("\t\tImplicit name " + refname + " is not allowed");
}
}
checkNamesAllowed(errlist, names, el);
}
}
/**
* Checks validity of nodedisplays.
* Checks whether only allowed attributes where used for
* base nodedisplays and nodedisplayrefs.
*
* Also checks whether the defined data-nodes are allowed against the scheme of the corresponding nodedisplay
*
* @param lgui
* @return found errors
*/
public static ErrorList checkNodedisplays(LguiType lgui) {
ErrorList res = new ErrorList();
List<GobjectType> gobjects = getGraphicalObjects(lgui);
//Search all nodedisplays and check their attributes
for (GobjectType gobj : gobjects) {
if (gobj instanceof Nodedisplay) {
Nodedisplay dis = (Nodedisplay)gobj;
res.addMessage("Errors for Nodedisplay " + dis.getId());
//This part is now done by xsl-file
// checkAttributesAllowedForNodedisplay(dis.getRefto()!=null, res, dis.getData(), new ArrayList<Integer>());
checkDataNodesinScheme(res, dis.getData(), new ArrayList<Integer>(), dis.getScheme());
}
}
return res;
}
private static final String line="-----------------------------------";
}