dadc13aa7ee3e926a894d7cfbbe846c69d82c7b9
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / java / LoggingModule.java
1 package org.simantics.scl.compiler.elaboration.java;
2
3 import org.cojen.classfile.TypeDesc;
4 import org.osgi.service.component.annotations.Component;
5 import org.simantics.scl.compiler.commands.CommandSession;
6 import org.simantics.scl.compiler.common.names.Name;
7 import org.simantics.scl.compiler.constants.JavaMethod;
8 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
9 import org.simantics.scl.compiler.elaboration.expressions.EApply;
10 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
11 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
12 import org.simantics.scl.compiler.elaboration.expressions.Expression;
13 import org.simantics.scl.compiler.elaboration.macros.MacroRule;
14 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
15 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
16 import org.simantics.scl.compiler.module.ConcreteModule;
17 import org.simantics.scl.compiler.types.TCon;
18 import org.simantics.scl.compiler.types.Type;
19 import org.simantics.scl.compiler.types.Types;
20 import org.simantics.scl.compiler.types.kinds.Kinds;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 import org.slf4j.Marker;
24
25 @Component
26 public class LoggingModule extends ConcreteModule {
27
28     private static final String[] LOGGING_METHODS = new String[] {
29             "trace", "debug", "info", "warn", "error" 
30     };
31     
32     public static final TCon Throwable = Types.con("Prelude", "Throwable");
33
34     public LoggingModule() {
35         super("LoggingJava");
36         
37         // Logger
38         TCon Logger = Types.con(getName(), "Logger");
39         StandardTypeConstructor loggerConstructor = new StandardTypeConstructor(Logger, Kinds.STAR, TypeDesc.forClass(Logger.class));
40         loggerConstructor.external = true;
41         addTypeDescriptor("Logger", loggerConstructor);
42
43         // Marker
44         TCon Marker = Types.con(getName(), "Marker");
45         StandardTypeConstructor markerConstructor = new StandardTypeConstructor(Marker, Kinds.STAR, TypeDesc.forClass(Marker.class));
46         markerConstructor.external = true;
47         addTypeDescriptor("Marker", markerConstructor);
48         
49         // Common types
50         Type isEnabledType = Types.functionE(Types.PUNIT, Types.PROC, Types.BOOLEAN);
51         Type loggingType = Types.functionE(Types.STRING, Types.PROC, Types.UNIT);
52         Type loggingTypeWithMarker = Types.functionE(new Type[] { Marker, Types.STRING }, Types.PROC, Types.UNIT);
53         Type loggingTypeWithException = Types.functionE(new Type[] { Types.STRING, Throwable }, Types.PROC, Types.UNIT);
54         Type loggingTypeWithMarkerAndException = Types.functionE(new Type[] { Marker, Types.STRING, Throwable }, Types.PROC, Types.UNIT);
55
56         // Add logging methods
57         for(String methodName : LOGGING_METHODS) {
58             { // isEnabled :: <Proc> Boolean
59                 String completeMethodName = generateIsEnabledName(methodName);
60                 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", completeMethodName, Types.PROC, Types.BOOLEAN, Logger);
61                 SCLValue value = new SCLValue(Name.create(getName(), completeMethodName));
62                 value.setType(isEnabledType);
63                 value.setMacroRule(new MacroRule() {
64                     @Override
65                     public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
66                         ConcreteModule module = context.getCompilationContext().module;
67                         String identifier;
68                         if (module != null)
69                             identifier = module.getName().replaceAll("/", ".");
70                         else
71                             identifier = CommandSession.class.getName();
72                         apply.set(new ELiteral(javaMethod), new Expression[] {
73                                 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger)
74                         });
75                         return apply;
76                     }
77                 });
78                 addValue(value);
79             }
80             { // logging function with single String-parameter :: String -> <Proc> ()
81                 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING);
82                 SCLValue value = new SCLValue(Name.create(getName(), methodName));
83                 value.setType(loggingType);
84                 value.setMacroRule(new MacroRule() {
85                     @Override
86                     public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
87                         ConcreteModule module = context.getCompilationContext().module;
88                         String identifier;
89                         if (module != null)
90                             identifier = module.getName().replaceAll("/", ".");
91                         else
92                             identifier = CommandSession.class.getName();
93                         apply.set(new ELiteral(javaMethod), new Expression[] {
94                                 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
95                                 apply.parameters[0]
96                         });
97                         return apply;
98                     }
99                 });
100                 addValue(value);
101             }
102             { // logging function with two parameters  :: String -> Throwable -> <Proc> ()
103                 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING, Throwable);
104                 SCLValue value = new SCLValue(Name.create(getName(), methodName + "E"));
105                 value.setType(loggingTypeWithException);
106                 value.setMacroRule(new MacroRule() {
107                     @Override
108                     public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
109                         ConcreteModule module = context.getCompilationContext().module;
110                         String identifier;
111                         if (module != null)
112                             identifier = module.getName().replaceAll("/", ".");
113                         else
114                             identifier = CommandSession.class.getName();
115                         apply.set(new ELiteral(javaMethod), new Expression[] {
116                                 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
117                                 apply.parameters[0],
118                                 apply.parameters[1]
119                         });
120                         return apply;
121                     }
122                 });
123                 addValue(value);
124             }
125             { // logging function with two parameters  :: Marker -> String -> <Proc> ()
126                 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING);
127                 SCLValue value = new SCLValue(Name.create(getName(), methodName + "M"));
128                 value.setType(loggingTypeWithMarker);
129                 value.setMacroRule(new MacroRule() {
130                     @Override
131                     public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
132                         ConcreteModule module = context.getCompilationContext().module;
133                         String identifier;
134                         if (module != null)
135                             identifier = module.getName().replaceAll("/", ".");
136                         else
137                             identifier = CommandSession.class.getName();
138                         apply.set(new ELiteral(javaMethod), new Expression[] {
139                                 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
140                                 apply.parameters[0],
141                                 apply.parameters[1]
142                         });
143                         return apply;
144                     }
145                 });
146                 addValue(value);
147             }
148             { // logging function with three parameters  :: Marker -> String -> Throwable -> <Proc> ()
149                 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING, Throwable);
150                 SCLValue value = new SCLValue(Name.create(getName(), methodName + "ME"));
151                 value.setType(loggingTypeWithMarkerAndException);
152                 value.setMacroRule(new MacroRule() {
153                     @Override
154                     public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
155                         ConcreteModule module = context.getCompilationContext().module;
156                         String identifier;
157                         if (module != null)
158                             identifier = module.getName().replaceAll("/", ".");
159                         else
160                             identifier = CommandSession.class.getName();
161                         apply.set(new ELiteral(javaMethod), new Expression[] {
162                                 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
163                                 apply.parameters[0],
164                                 apply.parameters[1],
165                                 apply.parameters[2]
166                         });
167                         return apply;
168                     }
169                 });
170                 addValue(value);
171             }
172         }
173         
174         setParentClassLoader(LoggerFactory.class.getClassLoader());
175     }
176
177     private static String generateIsEnabledName(String level) {
178         return "is" + capitalizeFirstCharacter(level) + "Enabled";
179     }
180     
181     private static String capitalizeFirstCharacter(String input) {
182         return input.substring(0, 1).toUpperCase() + input.substring(1);
183     }
184 }