de.flapdoodle.wicket.detach.FieldInspectingDetachListener.java Source code

Java tutorial

Introduction

Here is the source code for de.flapdoodle.wicket.detach.FieldInspectingDetachListener.java

Source

/**
 * Copyright (C) 2011
 *   Michael Mosmann <michael@mosmann.de>
 *   Jan Bernitt <unknown@email.de>
 *
 * with contributions from
 *    nobody yet
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.flapdoodle.wicket.detach;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import org.apache.wicket.Component;
import org.apache.wicket.IDetachListener;
import org.apache.wicket.Page;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.flapdoodle.wicket.serialize.java.PreSerializeChecker;

/**
 * some trouble with listview
 * @author mosmann
 *
 */
public class FieldInspectingDetachListener implements IDetachListener {

    private static final Logger log = LoggerFactory.getLogger(FieldInspectingDetachListener.class);

    @Override
    public void onDetach(Component component) {
        Class<? extends Component> clazz = component.getClass();
        if (false)
            log.debug("detaching {} ", typeName(clazz));

        List<Field> fields = getAllFields(clazz);

        Map<Object, Boolean> hitMap = new IdentityHashMap<Object, Boolean>();
        checkFields(typeName(clazz) + "[path=" + component.getPath() + "]", hitMap, component, fields);
    }

    private String typeName(Class<? extends Component> clazz) {
        return "" + clazz.getName() + (clazz.isAnonymousClass() ? "(" + clazz.getSuperclass().getName() + ")" : "");
    }

    private void checkFields(String id, Map<Object, Boolean> hitMap, Object component, List<Field> fields) {
        for (Field f : fields) {
            if (isWorthALook(f)) {
                try {
                    if (false)
                        log.debug("inspect {}", f);

                    f.setAccessible(true);
                    Object value = f.get(component);
                    if (!hitMap.containsKey(value)) {
                        hitMap.put(value, true);
                        if (value != null) {
                            if (value instanceof LoadableDetachableModel) {
                                LoadableDetachableModel ldm = (LoadableDetachableModel) value;
                                if (ldm.isAttached()) {
                                    log.error(id + ": loadable model " + ldm + " in " + f + " is NOT detached ",
                                            new RuntimeException());
                                }
                            }

                            checkFields(id, hitMap, value, getAllFields(value.getClass()));
                        }
                    }
                } catch (IllegalArgumentException e) {
                    log.error("get value", e);
                } catch (IllegalAccessException e) {
                    log.error("get value", e);
                }
            }
        }

        if (component instanceof Component) {
            Component c = (Component) component;
            IModel<?> model = c.getDefaultModel();
            if (model != null) {
                checkFields(id, hitMap, model, getAllFields(model.getClass()));
            }
        }
    }

    private boolean isWorthALook(Field f) {
        Class<?> fieldType = f.getType();
        if (fieldType.isPrimitive())
            return false;
        Package fieldPackage = fieldType.getPackage();
        if (fieldPackage != null) {
            if (fieldPackage.getName().startsWith("java.lang."))
                return false;
        }
        if (Page.class.isAssignableFrom(fieldType))
            return false;
        if (f.getDeclaringClass() == Component.class) {
            if (f.getName().equals("parent")) {
                return false;
            }
            if (f.getName().equals("data")) {
                return false;
            }
        }
        if (Modifier.isStatic(f.getModifiers()))
            return false;
        return true;
    }

    private List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<Field>();
        fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        Class<?> superclass = clazz.getSuperclass();
        if (superclass != null) {
            fields.addAll(getAllFields(superclass));
        }
        return fields;
    }

    @Override
    public void onDestroyListener() {

    }

}