001    /*
002     * To change this template, choose Tools | Templates
003     * and open the template in the editor.
004     */
005    
006    package org.bridj.cpp.mfc;
007    
008    import org.bridj.BridJ;
009    import org.bridj.Callback;
010    import org.bridj.NativeObject;
011    import org.bridj.Pointer;
012    import org.bridj.util.Utils;
013    import org.bridj.cpp.CPPRuntime;
014    
015    import java.lang.reflect.Method;
016    import java.lang.reflect.Type;
017    import java.util.HashSet;
018    import java.util.Map;
019    import java.util.Set;
020    
021    /**
022     *
023     * @author Olivier
024     */
025    public class MFCRuntime extends CPPRuntime {
026        Method mfcGetMessageMap;
027            String mfcGetMessageMapMangling;
028            Callback mfcGetMessageMapCallback;
029    
030            Set<Class<?>> hasMessageMap = new HashSet<Class<?>>();
031    
032            @Override
033            public <T extends NativeObject> Class<? extends T> getActualInstanceClass(Pointer<T> pInstance, Type officialType) {
034            Class officialTypeClass = Utils.getClass(officialType);
035                    // For MFC classes, use GetRuntimeClass()
036                    if (CObject.class.isAssignableFrom(officialTypeClass)) {
037                            Pointer<CRuntimeClass> pClass = new CObject((Pointer)pInstance, this).GetRuntimeClass();
038                            if (pClass != null) {
039                                    CRuntimeClass rtc = pClass.get();
040                                    try {
041                                            Class<? extends T> type = (Class)getMFCClass(rtc.m_lpszClassName());
042                                            if (officialTypeClass == null || officialTypeClass.isAssignableFrom(type))
043                                                    return type;
044                                    } catch (ClassNotFoundException ex) {}
045                                    return officialTypeClass;
046                            }
047                    }
048                    
049                    // TODO Auto-generated method stub
050                    return super.getActualInstanceClass(pInstance, officialType);
051            }
052            
053            private Class<?> getMFCClass(Pointer<Byte> mLpszClassName) throws ClassNotFoundException {
054                    throw new ClassNotFoundException(mLpszClassName.getCString());
055            }
056    
057            public void getExtraFieldsOfNewClass(Class<?> type, Map<String, Type> out) {
058                    //super.getExtraFieldsOfNewClass(type, out);
059                    if (!hasMessageMap.contains(type))
060                            return;
061    
062                    out.put("messageMap", Pointer.class);
063            }
064            
065            public void getOverriddenVirtualMethods(Map<String, Pointer<?>> out) {
066                    //super.getVirtualMethodBindings(out);
067                    out.put("mfcGetMessageMap", Pointer.pointerTo(mfcGetMessageMapCallback));
068            }
069    
070            @Override
071            public void register(Type type) {
072                    super.register(type);
073            Class typeClass = Utils.getClass(type);
074    
075                    MessageMapBuilder map = new MessageMapBuilder();
076                    for (Method method : typeClass.getMethods()) {
077    
078                            OnCommand onCommand = method.getAnnotation(OnCommand.class);
079                            if (onCommand != null)
080                                    map.add(method, onCommand);
081    
082                            OnCommandEx onCommandEx = method.getAnnotation(OnCommandEx.class);
083                            if (onCommandEx != null)
084                                    map.add(method, onCommandEx);
085    
086                            OnUpdateCommand onUpdateCommand = method.getAnnotation(OnUpdateCommand.class);
087                            if (onUpdateCommand != null)
088                                    map.add(method, onUpdateCommand);
089    
090                            OnRegisteredMessage onRegisteredMessage = method.getAnnotation(OnRegisteredMessage.class);
091                            if (onRegisteredMessage != null)
092                                    map.add(method, onRegisteredMessage);
093    
094                            OnMessage onMessage = method.getAnnotation(OnMessage.class);
095                            if (onMessage != null)
096                                    map.add(method, onMessage);
097                    }
098                    if (!map.isEmpty())
099                            map.register(this, typeClass);
100    
101            }
102    }