Commit c846a62f authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ refined hover provider to indicate structure and content of structured data...

+ refined hover provider to indicate structure and content of structured data instances and message arguments, &3
parent 16b0e07e
Loading
Loading
Loading
Loading
+247 −8
Original line number Diff line number Diff line
package org.etsi.mts.tdl.ui.hover;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.ui.editor.hover.html.DefaultEObjectHoverProvider;
import org.etsi.mts.tdl.AnyValue;
import org.etsi.mts.tdl.AnyValueOrOmit;
import org.etsi.mts.tdl.CastDataUse;
import org.etsi.mts.tdl.CollectionDataInstance;
import org.etsi.mts.tdl.CollectionDataType;
import org.etsi.mts.tdl.DataElementUse;
import org.etsi.mts.tdl.DataUse;
import org.etsi.mts.tdl.Function;
import org.etsi.mts.tdl.LiteralValueUse;
import org.etsi.mts.tdl.Member;
import org.etsi.mts.tdl.MemberAssignment;
import org.etsi.mts.tdl.MemberReference;
import org.etsi.mts.tdl.Message;
import org.etsi.mts.tdl.NamedElement;
import org.etsi.mts.tdl.Parameter;
import org.etsi.mts.tdl.ParameterBinding;
import org.etsi.mts.tdl.SimpleDataInstance;
import org.etsi.mts.tdl.StructuredDataInstance;
import org.etsi.mts.tdl.StructuredDataType;
import org.etsi.mts.tdl.TestDescription;
@@ -34,34 +48,49 @@ public class TDLtxHoverProvider extends DefaultEObjectHoverProvider {
			for (Setting f : found) {
				f.getEObject();
			}
			html+="<br/></br>Referenced in: <b><ul><li>"+targets+"</li></ul></b></br</br>";
			html+="<br/></br>Referenced in: <b><ul><li>"+targets+"</li></ul></b></br>";
		}
		if (o instanceof StructuredDataType) {
			String members = getListOfMembers((StructuredDataType) o);
			html+="<br/></br>Members: <b>"+members+"</b></br</br>";
			html+="<br/></br>Members: <b>"+members+"</b></br>";
		}		
		if (o instanceof StructuredDataInstance) {
			StructuredDataInstance instance = (StructuredDataInstance) o;
			html+="<br/><br/>Type: <b>"+instance.getDataType().getName()+"</b>";
			String members = getListOfMembers((StructuredDataType) instance.getDataType());
			html+="<br/></br>Members: <b>"+members+"</b></br</br>";
			html+="<br/></br>Members: <b>"+members+"</b>";
			//TODO: merge assignments above?
			String unassigned = getListOfUnassignedMembers((StructuredDataType) instance.getDataType(), instance.getMemberAssignment());
			if (!unassigned.equals("<ul><li></li></ul>")) {
				html+="Unassigned Members: <b>"+unassigned+"</b></br</br>";
				html+="Unassigned Members: <b>"+unassigned+"</b>";
			}
			String contents = "";
			contents = getNestedListOfMembersWithValues(instance);
			html+="Contents: <br/><b>"+contents+"</b></br>";
			
		}		
		if (o instanceof Parameter) {
			html+="<br/><br/>Type: <b>"+((Parameter) o).getDataType().getName()+"</b>";
			if (((Parameter) o).getDataType() instanceof StructuredDataType) {
				String members = getListOfMembers((StructuredDataType) ((Parameter) o).getDataType());
				html+="<br/></br>Members: <b>"+members+"</b></br</br>";
				html+="<br/></br>Members: <b>"+members+"</b></br>";
				//not really possible to determine
//				String unbound = getListOfUnboundParameters(((StructuredDataType) ((Parameter) o).getDataType()), o);
//				html+="<br/></br>Unbound Parameters: <b>"+unbound+"</b></br</br>";
			}
		}
		//TODO: data use
		//TODO: data use -> partially done in data instance
		if (o instanceof DataUse) {
			html+="DATA";
		}
		if (o instanceof Message) {
			Message m = ((Message) o);
			html="Message: <b>"+m.getSourceGate().getComponent().getName()
					+" --> "+m.getTarget().get(0).getTargetGate().getComponent().getName()+"</b><br/>";
			String contents = "";
			contents = getNestedListOfMembersWithValues(m.getArgument());
			html+="Contents: <br/><b>"+contents+"</b></br>";
		}
		return html;
	}

@@ -73,6 +102,217 @@ public class TDLtxHoverProvider extends DefaultEObjectHoverProvider {
		return "<ul><li>"+members+"</li></ul>";
	}

	private String getNestedListOfMembersWithValues(StructuredDataInstance i) {
		StructuredDataType o = (StructuredDataType) i.getDataType();
		Map<Member, DataUse> assigned = i.getMemberAssignment().stream().collect(Collectors.toMap(MemberAssignment::getMember, MemberAssignment::getMemberSpec));
		String members = "";
		for (var m : o.allMembers()) {
			members += "<li>";
			members += m.getName();
			if (assigned.containsKey(m)) {
				members += " = " + getNestedListOfMembersWithValues(assigned.get(m));
			} else {
				//TODO: unassigned treatment
				members += " : <u><i>("+m.getDataType().getName()+")</i></u>"; 
			}
			//TODO: optional
			members += "</li>";
		}
		
//		String members = o.allMembers().stream()
//				.map(e -> e.getName() + " : "+e.getDataType().getName() + (e.isIsOptional() ? " (optional)" : "")
//						+ ((e.getDataType() instanceof StructuredDataType) ? 
//								"<ul><li>"+getNestedListOfMembersWithValues(e.get)+"</li></ul>" : "")
//				)
//				.collect(Collectors.joining("</li><li>"));
		return "<ul>"+members+"</ul>";
	}

	//TODO: split
	private String getNestedListOfMembersWithValues(DataUse u) {
		String content = "";
		//TODO: resolve reduction value
		if (u instanceof DataElementUse) {
			NamedElement dataElement = ((DataElementUse) u).getDataElement();
			if (dataElement!=null) {
				if (dataElement instanceof StructuredDataInstance) {
					//TODO: extract
					Map<Parameter, DataUse> assigned = getAssigned((StructuredDataInstance) dataElement);
					Map<Parameter, DataUse> bound = getBound(u);
					StructuredDataType o = (StructuredDataType) ((StructuredDataInstance) dataElement).getDataType();

					if (!u.getReduction().isEmpty()) {
						content += getReduction(u.getReduction(), assigned);
					} else {
						content += "<ul>" + getMembersWithOverrides(assigned, bound, o) + "</ul>";
					}
					//content += " = " + getNestedListOfMembersWithValues((StructuredDataInstance) dataElement);
				} else if (dataElement instanceof StructuredDataType) {
					content += getArguments(u);
				} else if (dataElement instanceof CollectionDataInstance) {
					EList<DataUse> itemList = ((CollectionDataInstance) dataElement).getItem();
					String items = "";
					for (var iu : itemList) {
						items += getNestedListOfMembersWithValues(iu); 
					}
					content += "<ui><li>"+items+"</li></ui>";
				} else if (dataElement instanceof CollectionDataType) {
					EList<DataUse> itemList = ((DataElementUse) u).getItem();
					String items = "";
					for (var iu : itemList) {
						items += "<li>("+((CollectionDataType)dataElement).getItemType().getName()+")"+getNestedListOfMembersWithValues(iu)+"</li>"; 
					}
					content += "<ol>"+items+"</ol>";
				} else if (dataElement instanceof SimpleDataInstance) {
					content += "<u><i>"+dataElement.getName()+"</i></u>";
				} else if (dataElement instanceof Parameter) {
					content += "<u><i>"+dataElement.getName()+"</i></u>";
				} else if (dataElement instanceof Function) {
					content += "-><u><i>"+dataElement.getName()+"</i></u>";
				}
			} else {
				content += getArguments(u);
			}
			//TODO: handle items
			//TODO: handle reduction
		} else if (u instanceof LiteralValueUse) {
			content += getLiteralValue((LiteralValueUse)u);
		} else if (u instanceof AnyValue) {
			content += "" + "?";
		} else if (u instanceof AnyValueOrOmit) {
			content += "" + "*";
		} else if (u instanceof CastDataUse) {
			Map<Parameter,DataUse> assigned = getAssignedOrBoundWithReduction(u);
			if (assigned.containsKey(null)) {
				content += getNestedListOfMembersWithValues(assigned.get(null));
			} else {
				content += "<ul>";
				for (var b : assigned.keySet()) {
					content += "<li>";
					content += b.getName();
					content += " = " + getNestedListOfMembersWithValues(assigned.get(b));
					content += "</li>";
				}
				content += "</ul>";
			}
//			content += getCast((CastDataUse)u);
		}
		//TODO: others?
		return content;
	}
	
	private Map<Parameter, DataUse> getBound(DataUse u) {
		Map<Parameter, DataUse> bound = u.getArgument()
				.stream().collect(Collectors.toMap(ParameterBinding::getParameter, ParameterBinding::getDataUse));
		return bound;
	}

	private Map<Parameter, DataUse> getAssigned(StructuredDataInstance instance) {
		Map<Parameter, DataUse> assigned = instance.getMemberAssignment()
				.stream().collect(Collectors.toMap(MemberAssignment::getMember, MemberAssignment::getMemberSpec));
		return assigned;
	}

	private String getReduction(EList<MemberReference> reduction, Map<Parameter, DataUse> assigned) {
		String content = ""; 
		DataUse ru = null;
		for (var r : reduction) {
			//TODO: handle indices?
			if (r.getMember() != null) {
				if (assigned.containsKey(r.getMember())) {
					ru = assigned.get(r.getMember());
					assigned = getAssignedOrBoundWithReduction(ru);
				}
			}
		}
		content += getNestedListOfMembersWithValues(ru);
		return content;
	}

	private Map<Parameter, DataUse> getAssignedOrBound(DataUse u) {
		Map<Parameter, DataUse> assigned = Collections.emptyMap();
		if (u instanceof DataElementUse) {
			if (((DataElementUse) u).getDataElement() instanceof StructuredDataInstance) {
				assigned = getAssigned((StructuredDataInstance) ((DataElementUse)u).getDataElement());
			} else if (((DataElementUse) u).getDataElement() instanceof StructuredDataType) {
				assigned = getBound(u);
			} else if (((DataElementUse) u).getDataElement() instanceof CollectionDataType) {
				//TODO: handle?
			}
			//TODO: also simple data instances, enums?
		} else if (u instanceof CastDataUse) {
			assigned = getAssignedOrBoundWithReduction(((CastDataUse) u).getDataUse());
		} else if (u instanceof LiteralValueUse) {
			assigned = Collections.singletonMap(null, u);
		} else if (u instanceof AnyValue) {
			assigned = Collections.singletonMap(null, u);
		} else if (u instanceof AnyValueOrOmit) {
			assigned = Collections.singletonMap(null, u);
		}
		return assigned;
	}

	private Map<Parameter, DataUse> getAssignedOrBoundWithReduction(DataUse u) {
		Map<Parameter, DataUse> assigned = getAssignedOrBound(u);
		if (!u.getReduction().isEmpty()) {
			DataUse ru = null;
			for (var r : u.getReduction()) {
				if (r.getMember() != null) {
					if (assigned.containsKey(r.getMember())) {
						ru = assigned.get(r.getMember());
						assigned = getAssignedOrBound(ru);
						//TODO: handle cast?
					}					
				}
			}
		}
		return assigned;
	}

	private String getLiteralValue(LiteralValueUse u) {
		String content = "";
		if (u.getValue() != null) {
			content += "\""+u.getValue()+"\"";
		} else if (u.getIntValue() != null) {
			content += u.getIntValue();
		} else if (u.getBoolValue() != null) {
			content += u.getBoolValue();
		}
		return content;
	}

	private String getMembersWithOverrides(Map<Parameter, DataUse> assigned, Map<Parameter, DataUse> bound, StructuredDataType o) {
		String members = "";
		for (var m : o.allMembers()) {
			members += "<li>";
			members += m.getName();
			if (bound.containsKey(m)) {
				members += " = " + getNestedListOfMembersWithValues(bound.get(m));
			} else if (assigned.containsKey(m)) {
				members += " = " + getNestedListOfMembersWithValues(assigned.get(m));
			} else {
				//TODO: unassigned treatment
				members += " : <u><i>("+m.getDataType().getName()+")</i></u>"; 
			}
			//TODO: optional
			members += "</li>";
		}
		return members;
	}

	private String getArguments(DataUse u) {
		String content = "";
		content += "<ul>";
		for (var b : u.getArgument()) {
			content += "<li>";
			content += b.getParameter().getName();
			content += " = " + getNestedListOfMembersWithValues(b.getDataUse());
			content += "</li>";
		}
		content += "</ul>";
		return content;
	}
	
	private String getListOfUnassignedMembers(StructuredDataType o, List<MemberAssignment> m) {
		List<Member> assigned = m.stream().map(e->e.getMember()).collect(Collectors.toList());
		String members = o.allMembers().stream()
@@ -94,7 +334,6 @@ public class TDLtxHoverProvider extends DefaultEObjectHoverProvider {
	
	protected String getHoverInfoAsHtml(TestObjective o) {
		String html = super.getHoverInfoAsHtml(o);
		System.out.println(html);
		return html;
	}