Adding Marker-support to Logging-module
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / java / LoggingModule.java
index c0e3be53c9efc1b20c1080ae3502d4a5be0b35fa..dadc13aa7ee3e926a894d7cfbbe846c69d82c7b9 100644 (file)
@@ -20,32 +20,64 @@ import org.simantics.scl.compiler.types.Types;
 import org.simantics.scl.compiler.types.kinds.Kinds;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.slf4j.Marker;
 
 @Component
 public class LoggingModule extends ConcreteModule {
 
-    private static String[] LOGGING_METHODS = new String[] {
+    private static final String[] LOGGING_METHODS = new String[] {
             "trace", "debug", "info", "warn", "error" 
     };
     
     public static final TCon Throwable = Types.con("Prelude", "Throwable");
 
     public LoggingModule() {
-        super("Logging");
-
+        super("LoggingJava");
+        
         // Logger
         TCon Logger = Types.con(getName(), "Logger");
         StandardTypeConstructor loggerConstructor = new StandardTypeConstructor(Logger, Kinds.STAR, TypeDesc.forClass(Logger.class));
         loggerConstructor.external = true;
         addTypeDescriptor("Logger", loggerConstructor);
 
+        // Marker
+        TCon Marker = Types.con(getName(), "Marker");
+        StandardTypeConstructor markerConstructor = new StandardTypeConstructor(Marker, Kinds.STAR, TypeDesc.forClass(Marker.class));
+        markerConstructor.external = true;
+        addTypeDescriptor("Marker", markerConstructor);
+        
         // Common types
+        Type isEnabledType = Types.functionE(Types.PUNIT, Types.PROC, Types.BOOLEAN);
         Type loggingType = Types.functionE(Types.STRING, Types.PROC, Types.UNIT);
+        Type loggingTypeWithMarker = Types.functionE(new Type[] { Marker, Types.STRING }, Types.PROC, Types.UNIT);
         Type loggingTypeWithException = Types.functionE(new Type[] { Types.STRING, Throwable }, Types.PROC, Types.UNIT);
+        Type loggingTypeWithMarkerAndException = Types.functionE(new Type[] { Marker, Types.STRING, Throwable }, Types.PROC, Types.UNIT);
 
         // Add logging methods
         for(String methodName : LOGGING_METHODS) {
-            {
+            { // isEnabled :: <Proc> Boolean
+                String completeMethodName = generateIsEnabledName(methodName);
+                JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", completeMethodName, Types.PROC, Types.BOOLEAN, Logger);
+                SCLValue value = new SCLValue(Name.create(getName(), completeMethodName));
+                value.setType(isEnabledType);
+                value.setMacroRule(new MacroRule() {
+                    @Override
+                    public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
+                        ConcreteModule module = context.getCompilationContext().module;
+                        String identifier;
+                        if (module != null)
+                            identifier = module.getName().replaceAll("/", ".");
+                        else
+                            identifier = CommandSession.class.getName();
+                        apply.set(new ELiteral(javaMethod), new Expression[] {
+                                new EExternalConstant(LoggerFactory.getLogger(identifier), Logger)
+                        });
+                        return apply;
+                    }
+                });
+                addValue(value);
+            }
+            { // logging function with single String-parameter :: String -> <Proc> ()
                 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING);
                 SCLValue value = new SCLValue(Name.create(getName(), methodName));
                 value.setType(loggingType);
@@ -67,7 +99,7 @@ public class LoggingModule extends ConcreteModule {
                 });
                 addValue(value);
             }
-            {
+            { // logging function with two parameters  :: String -> Throwable -> <Proc> ()
                 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING, Throwable);
                 SCLValue value = new SCLValue(Name.create(getName(), methodName + "E"));
                 value.setType(loggingTypeWithException);
@@ -90,9 +122,63 @@ public class LoggingModule extends ConcreteModule {
                 });
                 addValue(value);
             }
+            { // logging function with two parameters  :: Marker -> String -> <Proc> ()
+                JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING);
+                SCLValue value = new SCLValue(Name.create(getName(), methodName + "M"));
+                value.setType(loggingTypeWithMarker);
+                value.setMacroRule(new MacroRule() {
+                    @Override
+                    public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
+                        ConcreteModule module = context.getCompilationContext().module;
+                        String identifier;
+                        if (module != null)
+                            identifier = module.getName().replaceAll("/", ".");
+                        else
+                            identifier = CommandSession.class.getName();
+                        apply.set(new ELiteral(javaMethod), new Expression[] {
+                                new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
+                                apply.parameters[0],
+                                apply.parameters[1]
+                        });
+                        return apply;
+                    }
+                });
+                addValue(value);
+            }
+            { // logging function with three parameters  :: Marker -> String -> Throwable -> <Proc> ()
+                JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING, Throwable);
+                SCLValue value = new SCLValue(Name.create(getName(), methodName + "ME"));
+                value.setType(loggingTypeWithMarkerAndException);
+                value.setMacroRule(new MacroRule() {
+                    @Override
+                    public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
+                        ConcreteModule module = context.getCompilationContext().module;
+                        String identifier;
+                        if (module != null)
+                            identifier = module.getName().replaceAll("/", ".");
+                        else
+                            identifier = CommandSession.class.getName();
+                        apply.set(new ELiteral(javaMethod), new Expression[] {
+                                new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
+                                apply.parameters[0],
+                                apply.parameters[1],
+                                apply.parameters[2]
+                        });
+                        return apply;
+                    }
+                });
+                addValue(value);
+            }
         }
         
         setParentClassLoader(LoggerFactory.class.getClassLoader());
     }
 
+    private static String generateIsEnabledName(String level) {
+        return "is" + capitalizeFirstCharacter(level) + "Enabled";
+    }
+    
+    private static String capitalizeFirstCharacter(String input) {
+        return input.substring(0, 1).toUpperCase() + input.substring(1);
+    }
 }