blob: 7585099d1ca73b60afa633f2a753cf5f4f255fb9 [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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.eclipse.ptp.rm.lml.internal.core.elements.DataElement;
import org.eclipse.ptp.rm.lml.internal.core.elements.Nodedisplay;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeElement;
import org.eclipse.ptp.rm.lml.internal.core.elements.SchemeType;
/**
* This class is capable of checking implicit names given by refid-attributes
* faster than by creating all implicit names and then look if refid-values were created
* @author Carsten Karbach, FZ Juelich
*
*/
public class FastImpCheck {
private static ArrayList<ArrayList<Integer>> levels;
public static ArrayList<ArrayList<Integer>> getAllImpNameLevels(String impname, Object scheme) {
levels = new ArrayList<ArrayList<Integer>>();
impnameToAllPossibleLevel(impname, scheme, new ArrayList<Integer>() );
return levels;
}
/**
* transform implicit name into level-nrs if possible,
* otherwise return null
*
* only lower elements of scheme are interesting
*
* @param impname relative name, which might be defined in the given scheme
* @param scheme any scheme-element on any level
* @param nrs Level-Numbers till now
* @return
*/
public static ArrayList<Integer> impnameToOneLevel(String impname, Object scheme, ArrayList<Integer> nrs) {
List<SchemeElement> lower = LMLCheck.getLowerSchemeElements(scheme);
for (SchemeElement low : lower) {
Mask amask = new Mask(low);
int i = 1;
while (i <= impname.length() && ! amask.isOutputAllowed(impname.substring(0, i))) {
i++;
}
if (i > impname.length()) {
//No part-string is allowed for this mask
continue;
}
//Otherwise impname.substring(0, i) is allowed
while (i <= impname.length() && amask.isOutputAllowed(impname.substring(0, i))) {
int id = amask.getNumberOfLevelstring( impname.substring(0, i) );
nrs.add(id);//add current number
if (i == impname.length()) {//Solution found
return nrs;
}
else {//Go deeper
ArrayList<Integer> res = impnameToOneLevel( impname.substring(i) , low, nrs);
if (res != null) {
return res;
}
}
nrs.remove(nrs.size() -1 );//Remove number added on this recursion-level
i++;
}
}
return null;
}
/**
* transform implicit name into level-nrs if possible,
* generates all allowed solutions
*
* only lower elements of scheme are interesting
*
* @param impname relative name, which might be defined in the given scheme
* @param scheme any scheme-element on any level
* @param nrs Level-Numbers till now
* @return
*/
public static void impnameToAllPossibleLevel(String impname, Object scheme, ArrayList<Integer> nrs) {
List<SchemeElement> lower = LMLCheck.getLowerSchemeElements(scheme);
for(SchemeElement low: lower){
Mask amask = new Mask(low);
int i = 1;
while (i <= impname.length() && ! amask.isOutputAllowed(impname.substring(0, i))) {
i++;
}
if (i>impname.length()) {
//No part-string is allowed for this mask
continue;
}
//Otherwise impname.substring(0, i) is allowed
while (i <= impname.length() && amask.isOutputAllowed(impname.substring(0, i))) {
int id = amask.getNumberOfLevelstring( impname.substring(0, i));
nrs.add(id);//add current number
if (i == impname.length() ) {//Solution found
ArrayList<Integer> copy = LMLCheck.copyArrayList(nrs);
levels.add(copy);
}
else {//Go deeper
impnameToAllPossibleLevel(impname.substring(i), low, nrs);
}
nrs.remove(nrs.size() - 1);//Remove number added on this recursion-level
i++;
}
}
}
/**
* parses all coherent digits and puts them into a an arraylist
*
* p100-13, 0009-0-012 is transformed into 100,13,9,0,12 in an arraylist
*
* @param impname implicit name of a component of a parallel computer
* @param scheme where the implicit object is defined by for masks-access
* @return arraylist of level-numbers
*/
private static ArrayList<Integer> impnameToLevel(String impname, HashMap<Integer, Mask> pmasks) {
ArrayList<Integer> res = new ArrayList<Integer>();
int length = impname.length();
int sumlength = 0;
int level = 1;
while (sumlength < length) {
Mask amask = pmasks.get(level++);
if (amask == null) {//No mask for this level => error in parsing
// System.err.println("No mask for level "+level);
return null;
}
int alength = 0;//Length of the current mask-output
if (amask.getOutputLength() >= 0) {//fixed length
alength = amask.getOutputLength();
if (sumlength + alength > impname.length() ||
! amask.isOutputAllowed(impname.substring(sumlength, sumlength+alength))) {
return null;
}
}
else {
//Variable-length-mask
String rest = impname.substring(sumlength);
int i = 1;
//Find first part that is allowed
while (i <= rest.length() && ! amask.isOutputAllowed(rest.substring(0, i)) ) {
i++;
}
if (i <= rest.length()) {
//Find last part that is allowed
int j = i;
while (j <= rest.length() && amask.isOutputAllowed(rest.substring(0, j))){
j++;
}
alength = j - 1;
}
else {
return null;//Given output is not allowed
}
}
int nr = amask.getNumberOfLevelstring(impname.substring(sumlength, sumlength + alength));
res.add(nr);
sumlength += alength;
}
return res;
}
/**
* Has to be called for nodedisplayviews
* begin level with 1
* Searches all masks within the scheme-tag of the nodedisplay
* @param sel schemeelement
* @param level
*/
private static HashMap<Integer, Mask> findMasks(Object sel, int level, HashMap<Integer, Mask> masks){
List els=LMLCheck.getLowerSchemeElements(sel);
for(Object el:els){
SchemeElement asel=(SchemeElement) el;
if(! masks.containsKey(level) && asel.getMask()!=null){
masks.put(level, new Mask(asel) );
}
findMasks(asel, level+1, masks);
}
return masks;
}
/**
* Runs through data-tree and searches for refid-attributes
* Converts every refid into level-ids and searches given object
* within the scheme-definition of base nodedisplay
* adds errors to res, if refid-object does not exist within scheme
* @param data Data-Element of referencing nodedisplay
* @param masks mask-attributes of base nodedisplay
* @param scheme scheme-element of base nodedisplay
* @param res errors
* @return errorlist which occurred during checks
*/
private static ErrorList rekCheckRefids(Object data, SchemeType scheme, ErrorList res) {
List els = LMLCheck.getLowerDataElements(data);
if (els == null) {
return res;//Keine Unterelemente gefunden
}
for (int i = 0; i < els.size(); i++){
DataElement el = (DataElement) els.get(i);
String refname = el.getRefid();
if (refname != null) {
// ArrayList<Integer> level=impnameToLevel(refname, masks);
ArrayList<Integer> level = impnameToOneLevel(refname, scheme, new ArrayList<Integer>());
if (level == null) {
res.addError("\tError refid " + refname + " is not allowed corresponding to the scheme-tag");
}
else {
if (LMLCheck.getSchemeByLevels(level, scheme) == null) {
res.addError("\tError refid " + refname + " is not allowed corresponding to the scheme-tag");
}
}
}
rekCheckRefids(el, scheme, res);
}
return res;
}
/**
* searches for refid within referencing nodedisplay and return errors if these
* refids are not allowed concerning the scheme given by the base nodedisplay
* @param base
* @param ref
* @return
*/
public static ErrorList checkRefids(Nodedisplay base, Nodedisplay ref, ErrorList pres) {
ErrorList res;
if (pres == null) {
res = new ErrorList();
}
else {
res = pres;
}
rekCheckRefids(ref.getData(), base.getScheme(), res);
return res;
}
}