001package org.nasdanika.html.ecore; 002 003import java.nio.charset.StandardCharsets; 004import java.security.MessageDigest; 005import java.security.NoSuchAlgorithmException; 006import java.util.function.Function; 007 008import org.apache.commons.codec.binary.Hex; 009import org.eclipse.emf.common.util.EList; 010import org.eclipse.emf.ecore.EClass; 011import org.eclipse.emf.ecore.EClassifier; 012import org.eclipse.emf.ecore.EGenericType; 013import org.eclipse.emf.ecore.EOperation; 014import org.eclipse.emf.ecore.EPackage; 015import org.eclipse.emf.ecore.EParameter; 016import org.nasdanika.common.Context; 017import org.nasdanika.common.ProgressMonitor; 018import org.nasdanika.html.Fragment; 019import org.nasdanika.html.HTMLFactory; 020import org.nasdanika.html.Tag; 021import org.nasdanika.html.TagName; 022import org.nasdanika.html.bootstrap.Table; 023import org.nasdanika.html.model.app.Action; 024import org.nasdanika.html.model.app.AppFactory; 025import org.nasdanika.html.model.app.SectionStyle; 026 027public class EOperationActionSupplier extends ETypedElementActionSupplier<EOperation> implements EcoreActionSupplier { 028 029 public EOperationActionSupplier(EOperation value, Context context, java.util.function.Function<EPackage,String> ePackagePathComputer) { 030 super(value, context, ePackagePathComputer); 031 } 032 033 @Override 034 public Action execute(EClass contextEClass, ProgressMonitor progressMonitor) throws Exception { 035 Action action = super.execute(contextEClass, progressMonitor); 036 action.setSectionStyle(SectionStyle.HEADER); 037 038 EClass eContainingClass = eObject.getEContainingClass(); 039 040 EList<Action> sections = action.getSections(); 041 042 if (!eObject.getEParameters().isEmpty()) { 043 Action parametersCategory = AppFactory.eINSTANCE.createAction(); 044 parametersCategory.setText("Parameters"); 045 sections.add(parametersCategory); 046 EList<Action> parameters = parametersCategory.getSections(); 047 048 // Creating a digest of parameter types to make the id shorter. 049 MessageDigest md = MessageDigest.getInstance("SHA-256"); 050 051 for (EParameter ep: eObject.getEParameters()) { 052 EClassifier type = ep.getEType(); 053 String typeStr = type.eClass().getName() + "-" + encodeEPackage(type.getEPackage()) + "-" + type.getName() + ","; 054 md.update(typeStr.getBytes(StandardCharsets.UTF_8)); 055 056 parameters.add(adaptChild(ep).execute(contextEClass, progressMonitor)); 057 } 058 } 059 060 String signature = eOperationSignature(eObject, this::encodeEPackage); 061 062 StringBuilder idBuilder = new StringBuilder(encodeEPackage(eContainingClass.getEPackage())) 063 .append("-") 064 .append(eContainingClass.getName()) 065 .append("-") 066 .append(signature); 067 068 action.setId(idBuilder.toString()); 069 action.setName(signature); 070 071 // Exceptions 072 EList<EGenericType> eGenericExceptions = eObject.getEGenericExceptions(); 073 if (!eGenericExceptions.isEmpty()) { 074 HTMLFactory htmlFactory = context.get(HTMLFactory.class); 075 Fragment gstf = htmlFactory.fragment(TagName.h3.create("Exceptions")); 076 077 Tag list = TagName.ul.create(); 078 gstf.content(list); 079 080 for (EGenericType genericException: eGenericExceptions) { 081 Tag listItem = TagName.li.create(); 082 list.content(listItem); 083 genericType(genericException, contextEClass, listItem.getContent(), progressMonitor); 084 } 085 addContent(action, gstf.toString()); 086 } 087 088 return action; 089 } 090 091 public static String eOperationSignature(EOperation eOperation, Function<EPackage, String> ePackageEncoder) throws NoSuchAlgorithmException { 092 StringBuilder signatureBuilder = new StringBuilder(eOperation.eClass().getName()) 093 .append("-") 094 .append(eOperation.getName()); 095 096 if (!eOperation.getEParameters().isEmpty()) { 097 // Creating a digest of parameter types to make the id shorter. 098 MessageDigest md = MessageDigest.getInstance("SHA-256"); 099 100 for (EParameter ep: eOperation.getEParameters()) { 101 EClassifier type = ep.getEType(); 102 String typeStr = type.eClass().getName() + "-" + ePackageEncoder.apply(type.getEPackage()) + "-" + type.getName() + ","; 103 md.update(typeStr.getBytes(StandardCharsets.UTF_8)); 104 } 105 signatureBuilder.append("-").append(Hex.encodeHexString(md.digest())); 106 } 107 108 return signatureBuilder.toString(); 109 } 110 111 @Override 112 protected Table propertiesTable(EClass contextEClass, ProgressMonitor monitor) throws Exception { 113 Table table = super.propertiesTable(contextEClass, monitor); 114 if (contextEClass != null) { 115 addRow(table, "Declaring class").add(link(eObject.getEContainingClass(), contextEClass)); 116 } 117 return table; 118 } 119 120}