com.exedio.copernica.ItemForm.java Source code

Java tutorial

Introduction

Here is the source code for com.exedio.copernica.ItemForm.java

Source

/*
 * Copyright (C) 2004-2009  exedio GmbH (www.exedio.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package com.exedio.copernica;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;

import com.exedio.cope.BooleanField;
import com.exedio.cope.Cope;
import com.exedio.cope.DataField;
import com.exedio.cope.FinalViolationException;
import com.exedio.cope.FunctionField;
import com.exedio.cope.IntegrityViolationException;
import com.exedio.cope.Item;
import com.exedio.cope.StringLengthViolationException;
import com.exedio.cope.MandatoryViolationException;
import com.exedio.cope.Model;
import com.exedio.cope.NoSuchIDException;
import com.exedio.cope.SetValue;
import com.exedio.cope.Type;
import com.exedio.cope.UniqueViolationException;
import com.exedio.cope.pattern.Media;

final class ItemForm extends Form {
    static final String SAVE_BUTTON = "SAVE";
    static final String CHECK_BUTTON = "CHECK";
    static final String DELETE_BUTTON = "DELETE";
    static final String SECTION = "section";

    final Item item;
    final Type<? extends Item> type;
    /*TODO final*/ boolean hasFiles;
    boolean toSave = false;
    final CopernicaSection currentSection;
    final List<com.exedio.cope.Field<?>> displayedAttributes;
    boolean deleted = false;
    String deletedName = null;
    String deletedError = null;

    ItemForm(final ItemCop cop, final HttpServletRequest request) {
        super(request);

        this.item = cop.item;
        this.type = item.getCopeType();
        final CopernicaProvider provider = cop.provider;
        final Model model = provider.getModel();
        final List<com.exedio.cope.Field<?>> hiddenAttributes;
        final Collection<?> sections = provider.getSections(type);
        final ArrayList<Field> visibleFields = new ArrayList<Field>();

        boolean sectionButton = false;
        if (sections != null) {
            {
                CopernicaSection buttonSection = null;
                CopernicaSection previousSection = null;
                CopernicaSection firstSection = null;
                final String previousSectionParam = getParameter(SECTION);

                for (Iterator<?> i = sections.iterator(); i.hasNext();) {
                    final CopernicaSection section = (CopernicaSection) i.next();
                    if (firstSection == null)
                        firstSection = section;

                    final String id = section.getCopernicaID();
                    if (getParameter(id) != null) {
                        buttonSection = section;
                        sectionButton = true;
                        break;
                    }

                    if (id.equals(previousSectionParam))
                        previousSection = section;
                }
                if (buttonSection != null)
                    currentSection = buttonSection;
                else if (previousSection != null)
                    currentSection = previousSection;
                else
                    currentSection = firstSection;
            }

            displayedAttributes = new ArrayList<com.exedio.cope.Field<?>>(provider.getMainAttributes(type));
            hiddenAttributes = new ArrayList<com.exedio.cope.Field<?>>();
            for (Iterator<?> i = sections.iterator(); i.hasNext();) {
                final CopernicaSection section = (CopernicaSection) i.next();
                new Section(section.getCopernicaID(), section.getCopernicaName(cop.language));
                final Collection<? extends com.exedio.cope.Field<?>> sectionAttributes = section
                        .getCopernicaAttributes();
                if (section.equals(currentSection))
                    displayedAttributes.addAll(sectionAttributes);
                else
                    hiddenAttributes.addAll(sectionAttributes);
            }
        } else {
            currentSection = null;
            displayedAttributes = type.getFields();
            hiddenAttributes = Collections.<com.exedio.cope.Field<?>>emptyList();
        }
        final ArrayList<com.exedio.cope.Field<?>> attributes = new ArrayList<com.exedio.cope.Field<?>>(
                displayedAttributes.size() + hiddenAttributes.size());
        attributes.addAll(displayedAttributes);
        attributes.addAll(hiddenAttributes);

        final boolean delete = getParameter(DELETE_BUTTON) != null;
        if (delete) {
            deletedName = cop.provider.getDisplayName(cop, cop.language, item);
            try {
                item.deleteCopeItem();
                deleted = true;
                return;
            } catch (IntegrityViolationException e) {
                deletedError = deletedName + " could not be deleted.";
            }
        }

        final boolean save = getParameter(SAVE_BUTTON) != null;
        final boolean post = save || sectionButton || getParameter(CHECK_BUTTON) != null;
        boolean hasFilesTemp = false;

        for (final com.exedio.cope.Field<?> anyAttribute : attributes) {
            if (!anyAttribute.isFinal()) {
                if (anyAttribute instanceof FunctionField) {
                    final Field field = createField((FunctionField<?>) anyAttribute, post, cop, model);
                    toSave = true;
                    if (displayedAttributes.contains(anyAttribute))
                        visibleFields.add(field);
                } else if (anyAttribute instanceof DataField) {
                    toSave = true;
                    hasFilesTemp = true;
                }
            }
        }
        this.hasFiles = hasFilesTemp;

        if (save)
            save();
    }

    private final Field createField(final FunctionField<?> attribute, final boolean post, final ItemCop cop,
            final Model model) {
        return createField(attribute, this.item, attribute.getName(), post, cop, model);
    }

    private final Field createField(final FunctionField<?> attribute, final Item item, final String name,
            final boolean post, final ItemCop cop, final Model model) {
        if (attribute.isFinal())
            throw new RuntimeException(attribute.toString());

        if (attribute instanceof com.exedio.cope.EnumField) {
            final com.exedio.cope.EnumField<? extends Enum<?>> enumAttribute = (com.exedio.cope.EnumField<?>) attribute;
            if (post)
                return new EnumField(enumAttribute, cop);
            else
                return new EnumField(enumAttribute, enumAttribute.get(item), cop);
        } else if (attribute instanceof BooleanField) {
            final BooleanField boolAttribute = (BooleanField) attribute;
            if (attribute.isMandatory()) {
                if (post)
                    return new CheckboxField(this, attribute, name);
                else
                    return new CheckboxField(this, attribute, name, boolAttribute.get(item).booleanValue());
            } else {
                if (post)
                    return new BooleanEnumField(boolAttribute, cop);
                else
                    return new BooleanEnumField(boolAttribute, boolAttribute.get(item), cop);
            }
        } else if (attribute instanceof com.exedio.cope.IntegerField) {
            if (post)
                return new IntegerField(this, attribute, name);
            else
                return new IntegerField(this, attribute, name,
                        ((com.exedio.cope.IntegerField) attribute).get(item));
        } else if (attribute instanceof com.exedio.cope.LongField) {
            if (post)
                return new LongField(this, attribute, name);
            else
                return new LongField(this, attribute, name, ((com.exedio.cope.LongField) attribute).get(item));
        } else if (attribute instanceof com.exedio.cope.DoubleField) {
            if (post)
                return new DoubleField(this, attribute, name);
            else
                return new DoubleField(this, attribute, name, ((com.exedio.cope.DoubleField) attribute).get(item));
        } else if (attribute instanceof com.exedio.cope.DateField) {
            if (post)
                return new DateField(this, attribute, name);
            else
                return new DateField(this, attribute, name, ((com.exedio.cope.DateField) attribute).get(item));
        } else if (attribute instanceof com.exedio.cope.DayField) {
            if (post)
                return new DayField(this, attribute, name);
            else
                return new DayField(this, attribute, name, ((com.exedio.cope.DayField) attribute).get(item));
        } else if (attribute instanceof com.exedio.cope.StringField) {
            if (post)
                return new StringField(this, attribute, name);
            else
                return new StringField(this, attribute, name, ((com.exedio.cope.StringField) attribute).get(item));
        } else if (attribute instanceof com.exedio.cope.ItemField) {
            if (post)
                return new ItemField(attribute, name, model, cop);
            else
                return new ItemField(attribute, name, ((com.exedio.cope.ItemField<?>) attribute).get(item), model,
                        cop);
        } else {
            throw new RuntimeException(attribute.getClass().toString());
        }
    }

    public class ItemField extends TextField {
        final Model model;
        final ItemCop cop;
        final Item content;

        /**
         * Constructs a form field with an initial value.
         */
        public ItemField(final Object key, final String name, final Item value, final Model model,
                final ItemCop cop) {
            super(ItemForm.this, key, name, (value == null) ? "" : value.getCopeID());

            this.model = model;
            this.cop = cop;
            this.content = value;
        }

        /**
         * Constructs a form field with a value obtained from the submitted form.
         */
        public ItemField(final Object key, final String name, final Model model, final ItemCop cop) {
            super(ItemForm.this, key, name);
            this.model = model;
            this.cop = cop;

            final String value = this.value;
            if (value.length() > 0) {
                Item parsed = null;
                try {
                    parsed = model.getItem(value);
                } catch (NoSuchIDException e) {
                    error = e.getMessage();
                }
                content = error == null ? parsed : null;
            } else
                content = null;
        }

        @Override
        public void writeIt(final PrintStream out) {
            super.writeIt(out);
            ItemCop_Jspm.write(out, this);
        }

        @Override
        public Object getContent() {
            return content;
        }

    }

    final class EnumField extends RadioField {
        private static final String VALUE_NULL = "null";

        final com.exedio.cope.EnumField<? extends Enum<?>> attribute;
        final Enum<?> content;

        /**
         * Constructs a form field with an initial value.
         */
        EnumField(final com.exedio.cope.EnumField<? extends Enum<?>> attribute, final Enum<?> value,
                final ItemCop cop) {
            super(ItemForm.this, attribute, attribute.getName(), (value == null) ? VALUE_NULL : value.name());

            this.attribute = attribute;
            this.content = value;
            addOptions(cop);
        }

        /**
         * Constructs a form field with a value obtained from the submitted form.
         */
        EnumField(final com.exedio.cope.EnumField<? extends Enum<?>> attribute, final ItemCop cop) {
            super(ItemForm.this, attribute, attribute.getName());

            this.attribute = attribute;
            addOptions(cop);

            final String value = this.value;
            if (VALUE_NULL.equals(value))
                content = null;
            else {
                content = attribute.getValue(value);
                if (content == null)
                    throw new RuntimeException(value);
            }
        }

        private void addOptions(final ItemCop cop) {
            if (!attribute.isMandatory()) {
                addOption(VALUE_NULL, cop.getDisplayNameNull());
            }
            for (final Enum<?> currentValue : attribute.getValues()) {
                final String currentCode = currentValue.name();
                final String currentName = cop.getDisplayName(currentValue);
                addOption(currentCode, currentName);
            }
        }

        @Override
        public Object getContent() {
            return content;
        }

    }

    final class BooleanEnumField extends RadioField {
        private static final String VALUE_NULL = "null";
        private static final String VALUE_ON = "on";
        private static final String VALUE_OFF = "off";

        final Boolean content;

        /**
         * Constructs a form field with an initial value.
         */
        BooleanEnumField(final BooleanField attribute, final Boolean value, final ItemCop cop) {
            super(ItemForm.this, attribute, attribute.getName(),
                    value == null ? VALUE_NULL : value.booleanValue() ? VALUE_ON : VALUE_OFF);

            this.content = value;
            addOptions(cop);
        }

        /**
         * Constructs a form field with a value obtained from the submitted form.
         */
        BooleanEnumField(final BooleanField attribute, final ItemCop cop) {
            super(ItemForm.this, attribute, attribute.getName());
            addOptions(cop);

            final String value = this.value;
            if (VALUE_NULL.equals(value))
                content = null;
            else if (VALUE_ON.equals(value))
                content = Boolean.TRUE;
            else if (VALUE_OFF.equals(value))
                content = Boolean.FALSE;
            else
                throw new RuntimeException(value);
        }

        private final void addOptions(final ItemCop cop) {
            addOption(VALUE_NULL, cop.getDisplayNameNull());
            addOption(VALUE_ON, cop.getDisplayNameOn());
            addOption(VALUE_OFF, cop.getDisplayNameOff());
        }

        @Override
        public Object getContent() {
            return content;
        }
    }

    private void save() {
        final ArrayList<SetValue<?>> setValues = new ArrayList<SetValue<?>>();

        for (Iterator<?> i = getFields().iterator(); i.hasNext();) {
            final Field field = (Field) i.next();
            if (field.key instanceof DataField) {
                final DataField attribute = (DataField) field.key;
                final Media media = Media.get(attribute);
                final FileItem fileItem = getParameterFile(attribute.getName());

                if (fileItem != null) {
                    String contentType = fileItem.getContentType();
                    if (contentType != null) {
                        // fix for MSIE behaviour
                        if ("image/pjpeg".equals(contentType))
                            contentType = "image/jpeg";

                        try {
                            final InputStream data = fileItem.getInputStream();
                            media.set(item, data, contentType);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
            if (field.error == null) {
                final FunctionField<?> attribute = (FunctionField<?>) field.key;
                setValues.add(Cope.mapAndCast(attribute, field.getContent()));
            }
        }
        try {
            item.set(setValues.toArray(new SetValue<?>[setValues.size()]));
        } catch (MandatoryViolationException e) {
            final Field field = getFieldByKey(e.getFeature());
            field.error = "error.notnull:" + e.getFeature().toString();
        } catch (FinalViolationException e) {
            throw new RuntimeException(e);
        } catch (UniqueViolationException e) {
            final Field field = getFieldByKey(e.getFeature().getFields().iterator().next());
            field.error = e.getClass().getName();
        } catch (StringLengthViolationException e) {
            final Field field = getFieldByKey(e.getFeature());
            field.error = e.getClass().getName();
        }
    }
}