66import java .util .HashMap ;
77import java .util .List ;
88import java .util .Map ;
9+ import java .awt .Color ;
10+ import java .nio .charset .StandardCharsets ;
11+
12+ import java .security .MessageDigest ;
13+ import java .security .NoSuchAlgorithmException ;
914
1015import org .apache .log4j .Level ;
1116import org .apache .log4j .Logger ;
@@ -154,7 +159,9 @@ private static List<AnalysisConstraint> parseConstraints(WebEditorDfd webEditorD
154159 return webEditorDfd .constraints ().stream ()
155160 .filter (it -> it .constraint () != null && !it .constraint ().isEmpty ())
156161 .map (it -> {
157- return AnalysisConstraint .fromString (new StringView (it .constraint ())).getResult ();
162+ var constraint = AnalysisConstraint .fromString (new StringView (it .constraint ())).getResult ();
163+ constraint .setName (it .name ());
164+ return constraint ;
158165 }).toList ();
159166 }
160167
@@ -176,44 +183,67 @@ private static List<DSLResult> runAnalysis(DataFlowDiagramAndDictionary dfd, Lis
176183 }
177184
178185 private static WebEditorDfd annotateViolations (WebEditorDfd webEditorDfd , List <DSLResult > violations ) {
179- Map <Child , String > nodeToAnnotationMap = new HashMap <>();
186+ Map <Child , List < String > > nodeToAnnotationMap = new HashMap <>();
180187
181188 for (int i = 0 ; i < violations .size (); i ++) {
182- final int index = i ;
183- violations . get ( i ) .getMatchedVertices ().stream ().forEach (it -> {
189+ var violation = violations . get ( i ) ;
190+ violation .getMatchedVertices ().stream ().forEach (it -> {
184191 var node = webEditorDfd .model ().children ().stream ()
185192 .filter (child -> child .id ().equals (((Node )it .getReferencedElement ()).getId ())).findFirst ().orElseThrow ();
186- var annotation = "" ;
193+ nodeToAnnotationMap . putIfAbsent ( node , new ArrayList <>()) ;
187194 if (nodeToAnnotationMap .containsKey (node )) {
188- annotation = nodeToAnnotationMap .get (node );
189- annotation += "\n " ;
195+ nodeToAnnotationMap .get (node ).add ("Constraint " + violation .getName () + " violated" );
190196 }
191- annotation += "Constraint " + index + " violated" ;
192- nodeToAnnotationMap .put (node , annotation );
193197 });
194198 }
195199
196200 List <Child > newChildren = new ArrayList <>();
197201
198202 for (Child child : webEditorDfd .model ().children ()) {
199203 if (nodeToAnnotationMap .containsKey (child )) {
200- StringBuilder builder = new StringBuilder ();
201- if (child .annotation () != null ) builder .append (child .annotation ().message ().toString ());
202- if (builder .toString () != "" ) builder .append ("\n " );
203- builder .append (nodeToAnnotationMap .get (child ));
204+ var annotations = child .annotations ();
205+ nodeToAnnotationMap .get (child ).forEach (annotation -> {
206+ annotations .add (new Annotation (annotation , "bolt" , stringToColorHex (annotation )));
207+ });
208+
204209
205- var annotation = new Annotation (builder .toString (), "bolt" , "#ff0000" );
206210
207- var newChild = new Child (child .text (), child .labels (), child .ports (), child .id (), child .type (), null , null ,annotation , child .children ());
211+ var newChild = new Child (child .text (), child .labels (), child .ports (), child .id (), child .type (), null , null , annotations , child .children ());
208212 newChildren .add (newChild );
209213 }
210214 }
211215
212- webEditorDfd .model ().children ().removeAll (nodeToAnnotationMap .keySet ());
216+ var nodesToRemove = new ArrayList <Child >();
217+
218+ nodeToAnnotationMap .keySet ().forEach (node -> {
219+ for (Child child : webEditorDfd .model ().children ()) {
220+ if (child .id ().equals (node .id ())) {
221+ nodesToRemove .add (child );
222+ break ;
223+ }
224+ }
225+ });
226+
227+ webEditorDfd .model ().children ().removeAll (nodesToRemove );
213228 webEditorDfd .model ().children ().addAll (newChildren );
214229
215230 return webEditorDfd ;
216231 }
217232
218-
233+ public static String stringToColorHex (String input ) {
234+ byte [] hash ;
235+ try {
236+ MessageDigest md = MessageDigest .getInstance ("MD5" );
237+ hash = md .digest (input .getBytes (StandardCharsets .UTF_8 ));
238+ } catch (NoSuchAlgorithmException e ) {
239+ hash = new byte [] {(byte )0x80 , (byte )0x80 , (byte )0x80 , 0 };
240+ }
241+ float hue = (hash [0 ] & 0xFF ) / 255f ;
242+ float saturation = 0.5f + ((hash [1 ] & 0xFF ) / 255f ) * 0.5f ;
243+ float brightness = 0.3f + ((hash [2 ] & 0xFF ) / 255f ) * 0.5f ;
244+ saturation = Math .max (0.5f , Math .min (saturation , 1.0f ));
245+ brightness = Math .max (0.3f , Math .min (brightness , 0.8f ));
246+ Color color = Color .getHSBColor (hue , saturation , brightness );
247+ return String .format ("#%02X%02X%02X" , color .getRed (), color .getGreen (), color .getBlue ());
248+ }
219249}
0 commit comments