
org.sdmlib.models.YamlIdMap Maven / Gradle / Ivy
Show all versions of SDMLib Show documentation
package org.sdmlib.models;
import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.uniks.networkparser.interfaces.SendableEntityCreator;
import de.uniks.networkparser.list.AbstractArray;
import de.uniks.networkparser.list.SimpleKeyValueList;
import de.uniks.networkparser.list.SimpleList;
import org.sdmlib.CGUtil;
/**
*
* Storyboard Yaml
* Start: Read graph from yaml text:
* - studyRight: University
* name: "\"Study \" Right\"And\"Fast now\""
* students: karli
* rooms: mathRoom artsRoom sportsRoom examRoom softwareEngineering
*
* - karli: Student
* id: 4242
* name: karli
*
* - albert: Prof
* topic: SE
*
* - Assignment content: points:
* matrixMult: "Matrix Multiplication" 5
* series: "Series" 6
* a3: Integrals 8
*
* - Room topic: credits: doors: students: assignments:
* mathRoom: math 17 null karli [matrixMult series a3]
* artsRoom: arts 16 mathRoom null null
* sportsRoom: sports 25 [mathRoom artsRoom]
* examRoom: exam 0 [sportsRoom artsRoom]
* softwareEngineering: "Software Engineering" 42 [artsRoom examRoom]
*
* Step 1: Call YamlIdMap.decode:
* YamlIdMap yamlIdMap = new YamlIdMap("org.sdmlib.test.examples.studyrightWithAssignments.model");
*
* University studyRight = (University) yamlIdMap.decode(yaml);
*
* Step 2: Decoded object structure:
*
* Check: root object exists "Study " Right"And"Fast now"
* Check: pojo albert exists org.sdmlib.test.examples.studyrightWithAssignments.model.Prof@2a67d89c
* Check: pojo attr SE actual SE
* Step 3: Generate Yaml from model:
* - u1: University
* name: "\"Study \" Right\"And\"Fast now\""
* students: s2
* rooms: r3 r4 r5 r6 r7
*
* - s2: Student
* name: karli
* id: 4242
* assignmentPoints: 0
* motivation: 0
* credits: 0
* university: u1
* in: r3
*
* - r3: Room
* topic: math
* credits: 17
* university: u1
* students: s2
* doors: r4 r5
* assignments: a8 a9 a10
*
* - r4: Room
* topic: arts
* credits: 16
* university: u1
* doors: r3 r5 r6 r7
*
* - r5: Room
* topic: sports
* credits: 25
* university: u1
* doors: r3 r4 r6
*
* - r6: Room
* topic: exam
* credits: 0
* university: u1
* doors: r5 r4 r7
*
* - r7: Room
* topic: "Software Engineering"
* credits: 42
* university: u1
* doors: r4 r6
*
* - a8: Assignment
* content: "Matrix Multiplication"
* points: 5
* room: r3
*
* - a9: Assignment
* content: Series
* points: 6
* room: r3
*
* - a10: Assignment
* content: Integrals
* points: 8
* room: r3
*
*
* Check: yaml starts with - u... true
*
*
* Step 5: now read from excel file
* * karli.setAssignmentPoints(0);
* * }
* * </pre>
* * <img src="doc-files/StudyRightWithAssignmentsStoryboardStep14.png" alt="StudyRightWithAssignmentsStoryboardStep14.png">
* * <p>6. (end situation/post-condition) Karli has completed the math topic and moves to sports.</p>
* * <p>Check: Karli's credits: 17 actual 17</p>
*
* doc/StudyRightStartSituation.txt
* - studyRight: University
* name: """Study Right"""
* students: karli
* rooms: mathRoom artsRoom sportsRoom examRoom softwareEngineering
*
* - karli: Student
* id: 4242
* name: karli
*
* - albert: Prof
* topic: SE
*
* - Assignment content: points:
* matrixMult: """Matrix Multiplication""" 5
* series: Series 6
* a3: Integrals 8
*
* - Room topic: credits: doors: students: assignments:
* mathRoom: math 17 null karli [matricMult series a3]
* artsRoom: arts 25 mathRoom
* sportsRoom: sports 25 [mathRoom artsRoom]
* examRoom: exam 0 [sportsRoom artsRoom]
* softwareEngineering: """Software Engineering""" 42 [artsRoom examRoom]
*
* result:
*
*/
public class YamlIdMap
{
private ArrayList packageNames;
private StringTokenizer tokenizer;
private String yaml;
private String userId = null;
private boolean decodingPropertyChange;
private SimpleKeyValueList objIdMap = new SimpleKeyValueList().withFlag(AbstractArray.BIDI);
private int maxUsedIdNum = 0;
private Yamler yamler = new Yamler();
private HashMap attrTimeStamps = new HashMap<>();
public SimpleKeyValueList getObjIdMap()
{
return objIdMap;
}
public HashMap getAttrTimeStamps()
{
return attrTimeStamps;
}
/**
*
* Storyboard Yaml
* Start: Read graph from yaml text:
* - studyRight: University
* name: "\"Study \" Right\"And\"Fast now\""
* students: karli
* rooms: mathRoom artsRoom sportsRoom examRoom softwareEngineering
*
* - karli: Student
* id: 4242
* name: karli
*
* - albert: Prof
* topic: SE
*
* - Assignment content: points:
* matrixMult: "Matrix Multiplication" 5
* series: "Series" 6
* a3: Integrals 8
*
* - Room topic: credits: doors: students: assignments:
* mathRoom: math 17 null karli [matrixMult series a3]
* artsRoom: arts 16 mathRoom null null
* sportsRoom: sports 25 [mathRoom artsRoom]
* examRoom: exam 0 [sportsRoom artsRoom]
* softwareEngineering: "Software Engineering" 42 [artsRoom examRoom]
*
* Step 1: Call YamlIdMap.decode:
* YamlIdMap yamlIdMap = new YamlIdMap("org.sdmlib.test.examples.studyrightWithAssignments.model");
*
* University studyRight = (University) yamlIdMap.decode(yaml);
*
* Step 2: Decoded object structure:
*
* Check: root object exists "Study " Right"And"Fast now"
* Check: pojo albert exists org.sdmlib.test.examples.studyrightWithAssignments.model.Prof@2a67d89c
* Check: pojo attr SE actual SE
* Step 3: Generate Yaml from model:
* - u1: University
* name: "\"Study \" Right\"And\"Fast now\""
* students: s2
* rooms: r3 r4 r5 r6 r7
*
* - s2: Student
* name: karli
* id: 4242
* assignmentPoints: 0
* motivation: 0
* credits: 0
* university: u1
* in: r3
*
* - r3: Room
* topic: math
* credits: 17
* university: u1
* students: s2
* doors: r4 r5
* assignments: a8 a9 a10
*
* - r4: Room
* topic: arts
* credits: 16
* university: u1
* doors: r3 r5 r6 r7
*
* - r5: Room
* topic: sports
* credits: 25
* university: u1
* doors: r3 r4 r6
*
* - r6: Room
* topic: exam
* credits: 0
* university: u1
* doors: r5 r4 r7
*
* - r7: Room
* topic: "Software Engineering"
* credits: 42
* university: u1
* doors: r4 r6
*
* - a8: Assignment
* content: "Matrix Multiplication"
* points: 5
* room: r3
*
* - a9: Assignment
* content: Series
* points: 6
* room: r3
*
* - a10: Assignment
* content: Integrals
* points: 8
* room: r3
*
*
* Check: yaml starts with - u... true
*
*
* Step 5: now read from excel file
* * karli.setAssignmentPoints(0);
* * }
* * </pre>
* * <img src="doc-files/StudyRightWithAssignmentsStoryboardStep14.png" alt="StudyRightWithAssignmentsStoryboardStep14.png">
* * <p>6. (end situation/post-condition) Karli has completed the math topic and moves to sports.</p>
* * <p>Check: Karli's credits: 17 actual 17</p>
*
* doc/StudyRightStartSituation.txt
* - studyRight: University
* name: """Study Right"""
* students: karli
* rooms: mathRoom artsRoom sportsRoom examRoom softwareEngineering
*
* - karli: Student
* id: 4242
* name: karli
*
* - albert: Prof
* topic: SE
*
* - Assignment content: points:
* matrixMult: """Matrix Multiplication""" 5
* series: Series 6
* a3: Integrals 8
*
* - Room topic: credits: doors: students: assignments:
* mathRoom: math 17 null karli [matricMult series a3]
* artsRoom: arts 25 mathRoom
* sportsRoom: sports 25 [mathRoom artsRoom]
* examRoom: exam 0 [sportsRoom artsRoom]
* softwareEngineering: """Software Engineering""" 42 [artsRoom examRoom]
*
* result:
*
*/
private YamlIdMap()
{
// always pass package to constructor
}
/**
*
* Storyboard Yaml
* Start: Read graph from yaml text:
* - studyRight: University
* name: "\"Study \" Right\"And\"Fast now\""
* students: karli
* rooms: mathRoom artsRoom sportsRoom examRoom softwareEngineering
*
* - karli: Student
* id: 4242
* name: karli
*
* - albert: Prof
* topic: SE
*
* - Assignment content: points:
* matrixMult: "Matrix Multiplication" 5
* series: "Series" 6
* a3: Integrals 8
*
* - Room topic: credits: doors: students: assignments:
* mathRoom: math 17 null karli [matrixMult series a3]
* artsRoom: arts 16 mathRoom null null
* sportsRoom: sports 25 [mathRoom artsRoom]
* examRoom: exam 0 [sportsRoom artsRoom]
* softwareEngineering: "Software Engineering" 42 [artsRoom examRoom]
*
* Step 1: Call YamlIdMap.decode:
* YamlIdMap yamlIdMap = new YamlIdMap("org.sdmlib.test.examples.studyrightWithAssignments.model");
*
* University studyRight = (University) yamlIdMap.decode(yaml);
*
* Step 2: Decoded object structure:
*
* Check: root object exists "Study " Right"And"Fast now"
* Check: pojo albert exists org.sdmlib.test.examples.studyrightWithAssignments.model.Prof@2a67d89c
* Check: pojo attr SE actual SE
* Step 3: Generate Yaml from model:
* - u1: University
* name: "\"Study \" Right\"And\"Fast now\""
* students: s2
* rooms: r3 r4 r5 r6 r7
*
* - s2: Student
* name: karli
* id: 4242
* assignmentPoints: 0
* motivation: 0
* credits: 0
* university: u1
* in: r3
*
* - r3: Room
* topic: math
* credits: 17
* university: u1
* students: s2
* doors: r4 r5
* assignments: a8 a9 a10
*
* - r4: Room
* topic: arts
* credits: 16
* university: u1
* doors: r3 r5 r6 r7
*
* - r5: Room
* topic: sports
* credits: 25
* university: u1
* doors: r3 r4 r6
*
* - r6: Room
* topic: exam
* credits: 0
* university: u1
* doors: r5 r4 r7
*
* - r7: Room
* topic: "Software Engineering"
* credits: 42
* university: u1
* doors: r4 r6
*
* - a8: Assignment
* content: "Matrix Multiplication"
* points: 5
* room: r3
*
* - a9: Assignment
* content: Series
* points: 6
* room: r3
*
* - a10: Assignment
* content: Integrals
* points: 8
* room: r3
*
*
* Check: yaml starts with - u... true
*
*
* Step 5: now read from excel file
* * karli.setAssignmentPoints(0);
* * }
* * </pre>
* * <img src="doc-files/StudyRightWithAssignmentsStoryboardStep14.png" alt="StudyRightWithAssignmentsStoryboardStep14.png">
* * <p>6. (end situation/post-condition) Karli has completed the math topic and moves to sports.</p>
* * <p>Check: Karli's credits: 17 actual 17</p>
*
* doc/StudyRightStartSituation.txt
* - studyRight: University
* name: """Study Right"""
* students: karli
* rooms: mathRoom artsRoom sportsRoom examRoom softwareEngineering
*
* - karli: Student
* id: 4242
* name: karli
*
* - albert: Prof
* topic: SE
*
* - Assignment content: points:
* matrixMult: """Matrix Multiplication""" 5
* series: Series 6
* a3: Integrals 8
*
* - Room topic: credits: doors: students: assignments:
* mathRoom: math 17 null karli [matricMult series a3]
* artsRoom: arts 25 mathRoom
* sportsRoom: sports 25 [mathRoom artsRoom]
* examRoom: exam 0 [sportsRoom artsRoom]
* softwareEngineering: """Software Engineering""" 42 [artsRoom examRoom]
*
* result:
*
* @param packageNames Name of Package
*/
public YamlIdMap(String... packageNames)
{
Objects.requireNonNull(packageNames);
List list = Arrays.asList(packageNames);
this.packageNames = new ArrayList(list);
creatorMap = new CreatorMap(this.packageNames);
}
public Object decodeCSV(String fileName)
{
try
{
byte[] bytes = Files.readAllBytes(Paths.get(fileName));
String csvText = new String(bytes);
String yamlText = convertCsv2Yaml(csvText);
// System.out.println(yamlText);
return this.decode(yamlText);
} catch (IOException e)
{
Logger.getGlobal().log(Level.SEVERE, e.getMessage(), e);
}
return null;
}
private String convertCsv2Yaml(String csvText)
{
String[] split = csvText.split(";");
for (int i = 0; i < split.length; i++)
{
String token = split[i];
if (token.startsWith("\"") && token.endsWith("\""))
{
// already done
continue;
}
if (token.startsWith("\"") && !token.endsWith("\""))
{
// there is a semicolon within " ; " , recombine it
int j = i;
String nextToken;
while (true)
{
j++;
nextToken = split[j];
split[j] = "";
token = token + ";" + nextToken;
if (nextToken.endsWith("\""))
{
split[i] = token;
i = j;
break;
}
}
continue;
}
if (token.trim().length() == 0)
{
continue;
}
Pattern pattern = Pattern.compile("\\s");
Matcher matcher = pattern.matcher(token.trim());
boolean found = matcher.find();
if (found)
{
token = yamler.encapsulate(token);
split[i] = token;
}
}
StringBuilder buf = new StringBuilder();
for (int i = 0; i < split.length; i++)
{
buf.append(split[i]).append(" ");
}
return buf.toString();
}
public Object decode(String yaml, Object root)
{
getOrCreateKey(root);
decode(yaml);
return root;
}
public Object decode(String yaml)
{
decodingPropertyChange = false;
yamlChangeText = null;
this.yaml = yaml;
Object root = null;
yamler = new Yamler(yaml);
if ( ! yamler.getCurrentToken().equals("-"))
{
return yamler.decode(yaml);
}
root = parseObjectIds();
yamler = new Yamler(yaml);
parseObjectAttrs();
// reset property change decoding
this.setDecodingPropertyChange(false);
yamlChangeText = null;
return root;
}
private void parseObjectAttrs()
{
while ( ! "".equals(yamler.getCurrentToken()))
{
if ( ! "-".equals(yamler.getCurrentToken()) )
{
yamler.printError("'-' expected");
yamler.nextToken();
continue;
}
String key = yamler.nextToken();
if ( key.endsWith(":"))
{
// usual
parseUsualObjectAttrs();
continue;
}
else
{
parseObjectTableAttrs();
continue;
}
}
}
private void parseObjectTableAttrs()
{
// skip column names
String className = yamler.getCurrentToken();
SendableEntityCreator creator = getCreator(className);
yamler.nextToken();
ArrayList colNameList = new ArrayList();
while ( ! "".equals(yamler.getCurrentToken()) && yamler.getLookAheadToken().endsWith(":"))
{
String colName = yamler.stripColon(yamler.getCurrentToken());
colNameList.add(colName);
yamler.nextToken();
}
while ( ! "".equals(yamler.getCurrentToken()) && ! "-".equals(yamler.getCurrentToken()))
{
String objectId = yamler.stripColon(yamler.getCurrentToken());
yamler.nextToken();
Object obj = objIdMap.get(objectId);
// column values
int colNum = 0;
while ( ! "".equals(yamler.getCurrentToken()) && ! yamler.getCurrentToken().endsWith(":") && ! "-".equals(yamler.getCurrentToken()))
{
String attrName = colNameList.get(colNum);
if (yamler.getCurrentToken().startsWith("["))
{
String value = yamler.getCurrentToken().substring(1);
if (value.trim().equals(""))
{
value = yamler.nextToken();
}
setValue(creator, obj, attrName, value);
while (! "".equals(yamler.getCurrentToken()) && ! yamler.getCurrentToken().endsWith("]") )
{
yamler.nextToken();
value = yamler.getCurrentToken();
if (yamler.getCurrentToken().endsWith("]"))
{
value = yamler.getCurrentToken().substring(0, yamler.getCurrentToken().length()-1);
}
if ( ! value.trim().equals(""))
{
setValue(creator, obj, attrName, value);
}
}
}
else
{
setValue(creator, obj, attrName, yamler.getCurrentToken());
}
colNum++;
yamler.nextToken();
}
}
}
private void parseUsualObjectAttrs()
{
String objectId = yamler.stripColon(yamler.getCurrentToken());
String className = yamler.nextToken();
yamler.nextToken();
if (className.endsWith(".remove"))
{
objIdMap.remove(objectId);
// skip time stamp, if necessary
while ( ! yamler.getCurrentToken().equals("")
&& ! yamler.getCurrentToken().equals("-"))
{
yamler.nextToken();
}
return;
}
if (className.equals(".Map"))
{
LinkedHashMap map = (LinkedHashMap) objIdMap.get(objectId);
while (yamler.getCurrentToken().endsWith(":"))
{
String attrName = yamler.stripColon(yamler.getCurrentToken());
yamler.nextToken();
String value = "";
int valueStart = yamler.getCurrentPos();
// many values
while ( ! yamler.getCurrentToken().equals("")
&& ! yamler.getCurrentToken().endsWith(":"))
{
value = yaml.substring(valueStart, yamler.getCurrentPos() + yamler.getCurrentToken().length());
yamler.nextToken();
}
map.put(attrName, value);
}
}
else
{
SendableEntityCreator creator = getCreator(className);
Object obj = objIdMap.get(objectId);
// read attributes
while (!yamler.getCurrentToken().equals("") && !yamler.getCurrentToken().equals("-"))
{
String attrName = yamler.stripColon(yamler.getCurrentToken());
yamler.nextToken();
if (obj == null)
{
// no object created by parseObjectIds. Object has been removed.
// ignore attr changes
while (!yamler.getCurrentToken().equals("")
&& !yamler.getCurrentToken().endsWith(":")
&& !yamler.getCurrentToken().equals("-"))
{
yamler.nextToken();
}
continue;
}
// many values
while (!yamler.getCurrentToken().equals("")
&& !yamler.getCurrentToken().endsWith(":")
&& !yamler.getCurrentToken().equals("-"))
{
String attrValue = yamler.getCurrentToken();
if (yamler.getLookAheadToken().endsWith(".time:"))
{
String propWithTime = yamler.nextToken();
String newTimeStamp = yamler.nextToken();
String oldTimeStamp = attrTimeStamps.get(objectId + "." + attrName);
if (oldTimeStamp == null || oldTimeStamp.compareTo(newTimeStamp) <= 0)
{
this.setDecodingPropertyChange(true);
if (yamlChangeText == null)
{
yamlChangeText = yaml;
}
setValue(creator, obj, attrName, attrValue);
attrTimeStamps.put(objectId + "." + attrName, newTimeStamp);
}
}
else
{
setValue(creator, obj, attrName, attrValue);
}
yamler.nextToken();
}
}
}
}
private void setValue(SendableEntityCreator creator, Object obj, String attrName, String attrValue)
{
String type = "new";
if (attrName.endsWith(".remove"))
{
attrName = attrName.substring(0, attrName.length() - ".remove".length());
if (creator.getValue(obj, attrName) instanceof Collection)
{
type = SendableEntityCreator.REMOVE;
}
else
{
attrValue = null;
}
}
try
{
creator.setValue(obj, attrName, attrValue, type);
}
catch (Exception e)
{
// maybe a node
Object targetObj = objIdMap.get(attrValue);
if (targetObj != null)
{
creator.setValue(obj, attrName, targetObj, type);
}
}
}
private Object parseObjectIds()
{
Object root = null;
while ( ! "".equals(yamler.getCurrentToken()))
{
if ( ! "-".equals(yamler.getCurrentToken()) )
{
yamler.printError("'-' expected");
yamler.nextToken();
continue;
}
String key = yamler.nextToken();
if ( key.endsWith(":"))
{
// usual
Object now = parseUsualObjectId();
if (root == null) root = now;
continue;
}
else
{
Object now = parseObjectTableIds();
if (root == null) root = now;
continue;
}
}
return root;
}
private Object parseUsualObjectId()
{
String objectId = yamler.stripColon(yamler.getCurrentToken());
int pos = objectId.lastIndexOf('.');
String numPart = objectId.substring(pos + 2);
int objectNum = 0;
try
{
objectNum = Integer.parseInt(numPart);
}
catch (NumberFormatException e)
{
objectNum = objIdMap.size() + 1;
}
if (objectNum > maxUsedIdNum)
{
maxUsedIdNum = objectNum;
}
String className = yamler.nextToken();
Object obj = objIdMap.get(objectId);
String userId = null;
// skip attributes
while ( ! yamler.getCurrentToken().equals("") && ! yamler.getCurrentToken().equals("-"))
{
String token = yamler.nextToken();
if (token.endsWith(".time:"))
{
token = yamler.nextToken();
userId = token.substring(token.lastIndexOf('.') + 1);
}
}
boolean foreignChange = false;
if (userId != null)
{
int dotIndex = objectId.indexOf('.');
if (dotIndex > 0)
{
String ownerId = objectId.substring(0, dotIndex);
foreignChange = ! userId.equals(ownerId);
}
}
if (obj == null && ! className.endsWith(".remove") && ! foreignChange)
{
if (className.equals(".Map"))
{
obj = new LinkedHashMap();
}
else
{
SendableEntityCreator creator = getCreator(className);
obj = creator.getSendableInstance(false);
}
objIdMap.put(objectId, obj);
}
return obj;
}
private Object parseObjectTableIds()
{
Object root = null;
// skip column names
String className = yamler.getCurrentToken();
SendableEntityCreator creator = getCreator(className);
while ( ! "".equals(yamler.getCurrentToken()) && yamler.getLookAheadToken().endsWith(":"))
{
yamler.nextToken();
}
while ( ! "".equals(yamler.getCurrentToken()) && ! "-".equals(yamler.getCurrentToken()))
{
String objectId = yamler.stripColon(yamler.getCurrentToken());
yamler.nextToken();
Object obj = creator.getSendableInstance(false);
objIdMap.put(objectId, obj);
if (root == null) root = obj;
// skip column values
while (! "".equals(yamler.getCurrentToken()) && ! yamler.getCurrentToken().endsWith(":") && ! "-".equals(yamler.getCurrentToken()))
{
yamler.nextToken();
}
}
return root;
}
private Object parseObjList(String key, String second)
{
return null;
}
CreatorMap creatorMap;
public SendableEntityCreator getCreator(String clazzName)
{
return creatorMap.getCreator(clazzName);
}
public Object getObject(String objId)
{
return objIdMap.get(objId);
}
public String encode(Object... rootObjList)
{
SimpleList