ontopoly.components.FieldsEditor.java Source code

Java tutorial

Introduction

Here is the source code for ontopoly.components.FieldsEditor.java

Source

/*
 * #!
 * Ontopoly Editor
 * #-
 * Copyright (C) 2001 - 2013 The Ontopia Project
 * #-
 * 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 ontopoly.components;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.ontopia.utils.ObjectUtils;
import ontopoly.model.AssociationType;
import ontopoly.model.FieldAssignment;
import ontopoly.model.FieldDefinition;
import ontopoly.model.IdentityField;
import ontopoly.model.NameField;
import ontopoly.model.NameType;
import ontopoly.model.OccurrenceField;
import ontopoly.model.OccurrenceType;
import ontopoly.model.QueryField;
import ontopoly.model.RoleField;
import ontopoly.model.Topic;
import ontopoly.model.TopicType;
import ontopoly.models.FieldAssignmentModel;
import ontopoly.models.FieldDefinitionModel;
import ontopoly.models.MutableLoadableDetachableModel;
import ontopoly.models.TopicTypeModel;
import ontopoly.pages.AbstractOntopolyPage;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.IAjaxIndicatorAware;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.ResourceModel;

public class FieldsEditor extends Panel {

    protected static final boolean ISSUE_329_ENABLED = true;

    TopicTypeModel topicTypeModel;
    boolean readonly;

    ListView<FieldAssignmentModel> listView;
    MutableLoadableDetachableModel<List<FieldAssignmentModel>> fieldAssignmentModels;

    public FieldsEditor(String id, TopicTypeModel _topicTypeModel, final boolean readonly) {
        super(id);
        this.topicTypeModel = _topicTypeModel;
        this.readonly = readonly;
        setOutputMarkupId(true);

        // existing fields
        this.fieldAssignmentModels = new MutableLoadableDetachableModel<List<FieldAssignmentModel>>() {
            @Override
            protected List<FieldAssignmentModel> load() {
                List<FieldAssignment> fieldAssignments = topicTypeModel.getTopicType().getFieldAssignments();
                return FieldAssignmentModel.wrapInFieldAssignmentModels(fieldAssignments);
            }
        };

        this.listView = new ListView<FieldAssignmentModel>("existingFields", fieldAssignmentModels) {
            public void populateItem(final ListItem<FieldAssignmentModel> item) {

                FieldAssignmentModel fieldAssignmentModel = item.getModelObject();
                item.setRenderBodyOnly(true);

                Component component = new FieldsEditorExistingPanel("field", topicTypeModel, fieldAssignmentModel,
                        readonly) {
                    @Override
                    protected void onMoveAfter(FieldAssignmentModel fam_dg, FieldAssignmentModel fam_do,
                            AjaxRequestTarget target) {
                        // notify parent
                        onUpdate(target);
                    }

                    @Override
                    protected void onRemove(FieldAssignmentModel fam, AjaxRequestTarget target) {
                        TopicType topicType = topicTypeModel.getTopicType();
                        FieldAssignment fieldAssignment = fam.getFieldAssignment();
                        topicType.removeField(fieldAssignment.getFieldDefinition());
                        // notify parent
                        onUpdate(target);
                    }
                };
                component.setRenderBodyOnly(true);
                item.add(component);
            }
        };
        listView.setReuseItems(true);
        add(listView);

        WebMarkupContainer actionsContainer = new WebMarkupContainer("actions") {
            @Override
            public boolean isVisible() {
                return !FieldsEditor.this.readonly;
            }
        };
        add(actionsContainer);
        actionsContainer.add(new FieldDefinitionTypeLink("names") {
            @Override
            protected List<NameField> getFieldDefinitions() {
                List<NameField> fields = topicTypeModel.getTopicType().getTopicMap().getNameFields();
                filterFieldDefinitions(fields);
                return fields;
            }
        });
        actionsContainer.add(new OntopolyImageLink("create-name-field", "create.gif",
                new ResourceModel("create.new.name.type")) {
            @Override
            public void onClick(AjaxRequestTarget target) {
                TopicType topicType = topicTypeModel.getTopicType();
                NameType nameType = topicType.createNameType();
                redirectToTopic(nameType);
            }
        });
        actionsContainer.add(new FieldDefinitionTypeLink("occurrences") {
            @Override
            protected List<OccurrenceField> getFieldDefinitions() {
                List<OccurrenceField> fields = topicTypeModel.getTopicType().getTopicMap().getOccurrenceFields();
                filterFieldDefinitions(fields);
                return fields;
            }
        });
        actionsContainer.add(new OntopolyImageLink("create-occurrence-field", "create.gif",
                new ResourceModel("create.new.occurrence.type")) {
            @Override
            public void onClick(AjaxRequestTarget target) {
                TopicType topicType = topicTypeModel.getTopicType();
                OccurrenceType occurrenceType = topicType.createOccurrenceType();
                redirectToTopic(occurrenceType);
            }
        });
        actionsContainer.add(new FieldDefinitionTypeLink("associations") {
            @Override
            protected List<? extends FieldDefinition> getFieldDefinitions() {
                List<RoleField> fields = topicTypeModel.getTopicType().getTopicMap().getRoleFields();
                filterFieldDefinitions(fields);
                return fields;
            }
        });
        actionsContainer.add(new OntopolyImageLink("create-role-field", "create.gif",
                new ResourceModel("create.new.association.type")) {
            @Override
            public void onClick(AjaxRequestTarget target) {
                TopicType topicType = topicTypeModel.getTopicType();
                AssociationType associationType = topicType.createAssociationType();
                redirectToTopic(associationType);
            }
        });
        actionsContainer.add(new FieldDefinitionTypeLink("identities") {
            @Override
            protected List<? extends FieldDefinition> getFieldDefinitions() {
                List<IdentityField> fields = topicTypeModel.getTopicType().getTopicMap().getIdentityFields();
                filterFieldDefinitions(fields);
                return fields;
            }
        });
        actionsContainer.add(new FieldDefinitionTypeLink("queries") {
            @Override
            protected List<? extends FieldDefinition> getFieldDefinitions() {
                List<QueryField> fields = topicTypeModel.getTopicType().getTopicMap().getQueryFields();
                filterFieldDefinitions(fields);
                return fields;
            }

            @Override
            public boolean isVisible() {
                return ISSUE_329_ENABLED;
            }
        });
        actionsContainer.add(new OntopolyImageLink("create-query-field", "create.gif",
                new ResourceModel("create.new.query.field")) {
            @Override
            public void onClick(AjaxRequestTarget target) {
                TopicType topicType = topicTypeModel.getTopicType();
                QueryField queryField = topicType.createQueryField();
                redirectToTopic(queryField);
            }

            @Override
            public boolean isVisible() {
                return ISSUE_329_ENABLED;
            }
        });

        List<FieldDefinitionModel> fields = Collections.emptyList();
        add(createListView(fields));
    }

    private void filterFieldDefinitions(List<? extends FieldDefinition> result) {
        AbstractOntopolyPage page = (AbstractOntopolyPage) getPage();
        page.filterTopics(result);
    }

    private void redirectToTopic(Topic topic) {
        AbstractOntopolyPage page = (AbstractOntopolyPage) getPage();
        setResponsePage(page.getPageClass(topic), page.getPageParameters(topic));
        setRedirect(true);
    }

    private ListView<FieldDefinitionModel> createListView(final List<FieldDefinitionModel> fieldDefinitionModels) {
        ListView<FieldDefinitionModel> listView = new ListView<FieldDefinitionModel>("addFields",
                fieldDefinitionModels) {
            public void populateItem(final ListItem<FieldDefinitionModel> item) {

                FieldDefinitionModel fieldDefinitionModel = item.getModelObject();
                //item.setRenderBodyOnly(true);

                Component component = new FieldsEditorAddPanel("field", topicTypeModel, fieldDefinitionModel) {
                    @Override
                    protected void onAddField(TopicTypeModel topicTypeModel,
                            FieldDefinitionModel fieldDefinitionModel, AjaxRequestTarget target) {
                        // add field to topic type
                        topicTypeModel.getTopicType().addField(fieldDefinitionModel.getFieldDefinition());

                        // remove field definition from available list
                        fieldDefinitionModels.remove(fieldDefinitionModel);
                        @SuppressWarnings("rawtypes")
                        ListView pListView = (ListView) item.getParent();
                        pListView.removeAll();
                        onUpdate(target);
                    }
                };
                //component.setRenderBodyOnly(true);
                item.add(component);
            }
        };
        listView.setOutputMarkupId(true);
        listView.setReuseItems(true);
        return listView;
    }

    private String selectedTypeLinkId;

    private void replaceListView(FieldDefinitionTypeLink typeLink) {
        String typeLinkId = typeLink.getMarkupId();
        ListView<FieldDefinitionModel> afListView;
        if (ObjectUtils.different(typeLinkId, selectedTypeLinkId)) {
            // replaces the existing listview with a new one
            selectedTypeLinkId = typeLinkId;
            afListView = createListView(filterAndWrapInFieldDefinitions(typeLink.getFieldDefinitions()));
        } else {
            List<FieldDefinitionModel> fields = Collections.emptyList();
            afListView = createListView(fields);
            selectedTypeLinkId = null;
        }
        replace(afListView);
    }

    private List<FieldDefinitionModel> filterAndWrapInFieldDefinitions(
            List<? extends FieldDefinition> fieldDefinitions) {
        // resolve existing field definitions
        List<FieldAssignmentModel> fams = fieldAssignmentModels.getObject();
        Set<FieldDefinition> existingFieldDefinitions = new HashSet<FieldDefinition>(fams.size());
        Iterator<FieldAssignmentModel> iter = fams.iterator();
        while (iter.hasNext()) {
            FieldAssignmentModel fieldAssignmentModel = iter.next();
            existingFieldDefinitions.add(fieldAssignmentModel.getFieldAssignment().getFieldDefinition());
        }
        // filter and sort field definitions
        List<FieldDefinitionModel> result = new ArrayList<FieldDefinitionModel>(fieldDefinitions.size());
        Iterator<? extends FieldDefinition> fditer = fieldDefinitions.iterator();
        while (fditer.hasNext()) {
            FieldDefinition fieldDefinition = fditer.next();
            if (!existingFieldDefinitions.contains(fieldDefinition))
                result.add(new FieldDefinitionModel(fieldDefinition));
        }
        Collections.sort(result, new Comparator<FieldDefinitionModel>() {
            public int compare(FieldDefinitionModel o1, FieldDefinitionModel o2) {
                FieldDefinition fd1 = o1.getFieldDefinition();
                FieldDefinition fd2 = o2.getFieldDefinition();
                return ObjectUtils.compare(fd1.getFieldName(), fd2.getFieldName());
            }
        });
        return result;
    }

    private abstract class FieldDefinitionTypeLink extends AjaxFallbackLink<Object> implements IAjaxIndicatorAware {
        FieldDefinitionTypeLink(String id) {
            super(id);
        }

        protected abstract List<? extends FieldDefinition> getFieldDefinitions();

        @Override
        public void onClick(AjaxRequestTarget target) {
            replaceListView(this);
            target.addComponent(FieldsEditor.this);
        }

        public String getAjaxIndicatorMarkupId() {
            return "ajaxIndicator";
        }
    }

    protected void onUpdate(AjaxRequestTarget target) {
        listView.removeAll();
        fieldAssignmentModels.detach(); // make sure list of field assignments is reloaded
        target.addComponent(FieldsEditor.this);
    }

    @Override
    public void onDetach() {
        topicTypeModel.detach();
        //    listView.detach();
        //    fieldAssignmentModels.detach();
        //    addFieldsContainer.detach();
        super.onDetach();
    }

}